const mongoose = require('mongoose');
const ObjectId = mongoose.Types.ObjectId;
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const moment_timeZone = require('moment-timezone');
const fs = require('fs');
const path = require('path');


const {
    toStr,
    capitalizeWords,
    getUserRandomToken,
    getOtp,
    formatTime12Hour,
    convert12To24,
    convert24To12,
    noticeSender
} = require('../helper/helper_functions');

// db modules
const user_bank_details_module = require('../model/user_bank_details_module');
const game_result_history_module = require('../model/game_result_history_module');
const games_module = require('../model/games_module');
const user_module = require('../model/user_module');
const bid_history_module = require('../model/bid_history_module');
const wallet_trans_history_module = require('../model/wallet_trans_history_module');
const withdraw_fund_request_module = require('../model/withdraw_fund_request_module');
const admin_module = require('../model/admin_module');
const refer_details_module = require('../model/refer_details_module');
const fix_values_module = require('../model/fix_values_module');
const user_notification_module = require('../model/user_notification_module');
const player_ids_module = require('../model/player_ids_module');
const roulette_bid_history_module = require('../model/roulette_bid_history_module');
const user_device_record_module = require('../model/user_device_record_module');
const file_module = require('../model/file_module');
const notice_module = require('../model/notice_module');
const ideas_module = require('../model/ideas_module');
const admin_bank_detail_module = require('../model/admin_bank_detail_module');
const otp_module = require('../model/otp_module');
const admin_upi_update_record_module = require('../model/admin_upi_update_record_module');
const app_link_module = require('../model/app_link_module');
const game_rates_module = require('../model/game_rates_module');
const lottery_module = require('../model/lottery_module');
const lottery_tickets_module = require('../model/lottery_tickets_module');
const lottery_bid_history_module = require('../model/lottery_bid_history_module');
const weekday_games_module = require('../model/weekday_games_module');
const contact_settings_module = require('../model/contact_settings_module');
const starline_game_result_history_module = require('../model/starline_game_result_history_module');
const starline_bid_history_module = require('../model/starline_bid_history_module');
const starline_game_rates_module = require('../model/starline_game_rates_module');
const starline_games_module = require('../model/starline_games_module');
const gali_disswar_games_module = require('../model/gali_disswar_games_module');
const gali_disswar_bid_history_module = require('../model/gali_disswar_bid_history_module');
const gali_disswar_game_result_history_module = require('../model/gali_disswar_game_result_history_module');
const gali_disswar_game_rates_module = require('../model/gali_disswar_game_rates_module');
const how_to_play_module = require('../model/how_to_play_module');
const slider_images_module = require('../model/slider_images_module');
const qrcode_images_module = require('../model/qrcode_images_module');
const admin_set_result_module = require('../model/admin_set_result');

// utils functions
const { uniqRandom } = require('../utils/Ramdom_string');
const updateUserBalance = require('../utils/updateUserBalance');
const deductUserWallet = require('../utils/beditUser')
const { formatDateToDDMMYYYY, convertToISODate, getWeekdayNameInIST } = require('../utils/formatDateFromISO')
const { get12HoursTimeFromISO, getISOFrom12HoursTime } = require('../utils/getTimeFromISO');
const getISTDateObject = require('../utils/getISTDateObject');
const { menusData } = require('../utils/otherFix_values');
const mini_games_module = require('../model/mini_games_module');
const add_funds_module = require('../model/add_funds_module');

const ManualPayment = require('../model/admin_manual_payment_module');
const { emitToUser } = require('../utils/socketManager');



const changeWingoResult = async (req, res) => {
    try {
        const { key, value } = req.body;

        if (!key || value === undefined) {
            return res.status(400).json({ message: "Please provide key and value" });
        }

        // Allowed keys inside wingo
        const allowedKeys = ["wingo30", "wingo1", "wingo3", "wingo5", "wingo10"];
        if (!allowedKeys.includes(key)) {
            return res.status(400).json({ message: "Invalid wingo key" });
        }

        // Update only the specific wingo sub-key
        const updatedDoc = await admin_set_result_module.findOneAndUpdate(
            {},
            { $set: { [`wingo.${key}`]: value } },
            { new: true, upsert: true }
        );

        return res.status(200).json({ success: true, message: `Wingo ${key} updated successfully`, data: updatedDoc.wingo, });

    } catch (err) {
        console.log("error in changeWingoResult", err);
        return res.status(500).json({ success: false, message: `Wingo ${key} not updated ` });
    }
}

const isAlreadyLogin = async (req, res) => {
    try {
        let admin = req?.admin || {}
        return res.json({
            success: true,
            msg: "You already login",
            redirectRoute: menusData[admin?.accessMenus[0]] || '/dashboard',
            adminAccess: admin?.accessMenus
        });

    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: "Server error" });
    }
};

// const isAlreadyLogin = async (req, res) => {
//   try {
//     const admin = req?.admin || {};
//     const accessMenus = Array.isArray(admin?.accessMenus) ? admin.accessMenus : [];

//     return res.json({
//       success: true,
//       msg: "You already login",
//       redirectRoute: accessMenus.length > 0 ? (menusData[accessMenus[0]] || '/dashboard') : '/dashboard',
//       adminAccess: accessMenus
//     });

//   } catch (err) {
//     console.error(err);
//     return res.status(500).json({ success: false, msg: "Server error" });
//   }
// };

const loginCheck = async (req, res) => {
    try {
        if (!process?.env?.JWT_SECRET) {
            return res.status(500).json({ success: false, msg: "JWT secret not found" });
        }

        let { email = '', password = '' } = req.body || {};
        email = email.trim();
        password = password.trim();

        if (!email || !password) {
            return res.status(400).json({
                success: false,
                msg: "Email and password are required."
            });
        }

        // Optional: Enforce password strength
        // const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/;
        // if (!passwordRegex.test(password)) {
        //     return res.status(400).json({
        //         success: false,
        //         msg: "Password must be at least 8 characters and include uppercase, lowercase, number, and special character."
        //     });
        // }

        const user = await admin_module.findOne({ admin_email: email });

        if (!user) {
            return res.status(401).json({
                success: false,
                msg: "Invalid credentials."
            });
        }

        const isMatch = await bcrypt.compare(password, user.password);

        if (!isMatch) {
            return res.status(401).json({
                success: false,
                msg: "Invalid email or password."
            });
        }

        const token = jwt.sign(
            { admin: user },
            process.env.JWT_SECRET,
            { expiresIn: '7d' }
        );

        res.cookie("unique_jwt_token", token, {
            maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
            httpOnly: true,
            signed: true,
            secure: process.env.NODE_ENV === 'production' // Use true only on HTTPS in production
        });

        return res.status(200).json({
            success: true,
            testToken: token,
            msg: "Login successful. Redirecting...",
            redirectRoute: menusData[user?.accessMenus?.[0]] || '/dashboard'
        });

    } catch (err) {
        console.error("Login error:", err);
        return res.status(500).json({ success: false, msg: "Internal server error." });
    }
};

const unApprovedUserListGridData = async (req, res) => {
    try {
        const fields = [
            "user_name",           // "User",
            "mobile",              // "Mobile",
            "email",               // "Email",
            "last_update",         // "Date",
            "wallet_balance",      // "Balance",
            "betting_status",      // "Betting",
            "transfer_point_status", // "Transfer",
            "status",              // "Active",
        ];

        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) - 1 || 0;
        let searchValue = req?.body?.searchValue?.trim() || '';
        const fieldIndex = req?.body?.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "last_update";
        const orderDir = req?.body?.order || -1;

        const baseQuery = { betting_status: 0 };
        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);

            if (isNumeric) {
                searchValue = Number(searchValue);
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$mobile" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$wallet_balance" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        }
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { email: { $regex: `^${searchValue}`, $options: 'i' } },
                    ]
                };
            }
        }

        const finalQuery = { ...baseQuery, ...searchQuery };

        const userQuery = user_module.find(finalQuery)
            .sort({ [orderField]: orderDir })
            .limit(limit);

        if (!searchValue) {
            userQuery.skip(start * limit);
        }

        const [totalFiltered, users] = await Promise.all([
            user_module.countDocuments(finalQuery),
            userQuery.lean()
        ]);

        const data = users.map(user => ({
            ...user,
            user_name: user.user_name,
            mobile: user.mobile,
            email: user.email || "N/A",
            last_update: user.last_update
                ? moment_timeZone(user.last_update).tz('Asia/Kolkata').format('DD MMM YYYY, hh:mm A')
                : "N/A",
            wallet_balance: user.wallet_balance,
            userDB_id: user._id,
        }));

        return res.json({
            success: true,
            msg: "User list fetched successfully",
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (error) {
        console.error("Error in unApprovedUserListGridData:", error);
        return res.status(500).json({ success: false, msg: "Internal server error" });
    }
};

const blockDataFunction = async (req, res) => {
    try {
        const { userDB_id = "", collectionName = "", document_fieldName = "" } = req?.body || {};

        if (!userDB_id || !collectionName || !document_fieldName) {
            return res.status(400).json({ success: false, msg: 'Missing required fields' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid request ID" });
        }

        let Model;
        try {
            Model = mongoose.model(collectionName);
        } catch (e) {
            return res.status(400).json({ success: false, msg: 'Invalid collection name' });
        }

        const query = { _id: userDB_id };

        const result = await Model.findOne(query);
        if (!result) {
            return res.status(404).json({ success: false, msg: 'Record not found' });
        }

        const currentStatus = result[document_fieldName];
        let newStatus, msg;

        if (currentStatus === 1) {
            newStatus = 0;
            msg = 'Inactive';
        } else {
            newStatus = 1;
            msg = 'Active';
        }

        result[document_fieldName] = newStatus;
        if (result?.last_update) {
            result.last_update = getISTDateObject()
        }
        await result.save();

        return res.json({ success: true, msg: `${msg} Successfully`, last_update: formatDateToDDMMYYYY(result?.last_update) + " , " + get12HoursTimeFromISO(result?.last_update) || '' });
    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: 'Something went wrong' });
    }
};

// pending for payment getway automatic
// const autoFundRequestListGridData = async (req, res) => {
//     try {
//         const baseUrl = process?.env?.BASE_URL;
//         if (!baseUrl) {
//             return res.status(500).json({ success: false, msg: "Base URL not set" });
//         }

//         const fields = [
//             "user_name",
//             "amount",
//             "tx_request_number",
//             "payment_method",
//             "txn_ref",
//             "reject_remark",
//             "fund_payment_receipt",
//             "deposit_type",
//             "insert_date",
//             "fund_status",
//         ];

//         const limit = parseInt(req?.body?.length) || 10;
//         const start = parseInt(req?.body?.start) || 1;
//         const fieldIndex = req?.body?.fieldIndex || 0;
//         const orderField = fields[fieldIndex] || "insert_date";
//         const orderDir = req?.body?.order || -1;

//         let searchValue = req?.body?.searchValue?.trim() || '';
//         let searchQuery = {};

//         if (searchValue) {
//             console.log("searchValue");
//             const isNumeric = !isNaN(searchValue);
//             if (isNumeric) {
//                 searchQuery = {
//                     $or: [
//                         {
//                             $expr: {
//                                 $regexMatch: {
//                                     input: { $toString: "$amount" },
//                                     regex: `^${searchValue}`,
//                                     options: "i"
//                                 }
//                             }
//                         },
//                         {
//                             $expr: {
//                                 $regexMatch: {
//                                     input: { $toString: "$fund_status" },
//                                     regex: `^${searchValue}`,
//                                     options: "i"
//                                 }
//                             }
//                         },
//                         {
//                             $expr: {
//                                 $regexMatch: {
//                                     input: { $toString: "$deposit_type" },
//                                     regex: `^${searchValue}`,
//                                     options: "i"
//                                 }
//                             }
//                         },
//                     ]
//                 };
//             } else {
//                 searchQuery = {
//                     $or: [
//                         { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
//                         { txn_ref: { $regex: `^${searchValue}`, $options: 'i' } },
//                         { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
//                         { payment_method: { $regex: `^${searchValue}`, $options: 'i' } },
//                         { reject_remark: { $regex: `^${searchValue}`, $options: 'i' } },
//                     ]
//                 };
//             }
//         }

//         // Count Total Filtered Data
//         const totalDataAgg = await add_funds_module.aggregate([
//             {
//                 $lookup: {
//                     from: "users",
//                     localField: "userDB_id",
//                     foreignField: "_id",
//                     as: "userData"
//                 }
//             },
//             { $unwind: "$userData" },
//             {
//                 $project: {
//                     userDB_id: "$userData._id",
//                     user_name: "$userData.user_name",
//                     amount: 1,
//                     tx_request_number: 1,
//                     reject_remark: 1,
//                     deposit_type: 1,
//                     payment_method: 1,
//                     txn_ref: 1,
//                     fund_status: 1,
//                     insert_date: 1,
//                     deposit_type: 1,
//                     fund_payment_receipt: 1,
//                     isAction: {
//                         $cond: [
//                             { $ne: ['$fund_status', 0] },
//                             0,
//                             1
//                         ]
//                     }
//                 }
//             },
//             // { $match: searchQuery },
//             // { $count: "totalData" },
//         ]);

//         // console.log(`(((((((()))))) ~ adminController.js:456 ~ autoFundRequestListGridData ~ totalDataAgg:`, totalDataAgg);

//         const totalData = totalDataAgg[0]?.totalData || 0;

//         // console.log(`(((((((()))))) ~ adminController.js:460 ~ autoFundRequestListGridData ~ totalData:`, totalData);

//         // Build Main Pipeline
//         const pipeline = [
//             {
//                 $lookup: {
//                     from: "users",
//                     localField: "userDB_id",
//                     foreignField: "_id",
//                     as: "userData"
//                 }
//             },
//             { $unwind: "$userData" },
//             {
//                 $project: {
//                     userDB_id: "$userData._id",
//                     user_name: "$userData.user_name",
//                     amount: 1,
//                     tx_request_number: 1,
//                     payment_method: 1,
//                     txn_ref: 1,
//                     reject_remark: 1,
//                     fund_status: 1,
//                     insert_date: 1,
//                     deposit_type: 1,
//                     fund_payment_receipt: 1,
//                     isAction: {
//                         $cond: [
//                             { $ne: ['$fund_status', 0] },
//                             0,
//                             1
//                         ]
//                     }
//                 }
//             },
//             { $sort: { [orderField]: orderDir } },
//             { $match: searchQuery },
//         ];

//         if (!searchValue) {
//             pipeline.push({ $skip: (start -1) * limit });
//         }

//         pipeline.push({ $limit: limit });

//         // console.log(`(((((((()))))) ~ adminController.js:505 ~ autoFundRequestListGridData ~ pipeline:`, pipeline);

//         const fundRequests = await add_funds_module.aggregate(pipeline);

//         // console.log(`(((((((()))))) ~ adminController.js:507 ~ autoFundRequestListGridData ~ fundRequests:`, fundRequests);

//         // Format Insert Date to IST
//         const formattedFundRequests = fundRequests.map(v => ({
//             ...v,
//             insert_date: v.insert_date
//                 ? moment_timeZone(v.insert_date).tz("Asia/Kolkata").format("DD MMM YYYY, hh:mm:ss A")
//                 : "N/A",
//             receipt_url: v?.fund_payment_receipt && baseUrl
//                 ? `${baseUrl}/file/uploads/images/${v.fund_payment_receipt}`
//                 : null
//         }));

//         // console.log(`(((((((()))))) ~ adminController.js:520 ~ autoFundRequestListGridData ~ formattedFundRequests:`, formattedFundRequests);

//         return res.json({
//             success: true,
//             recordsFiltered: totalData,
//             data: formattedFundRequests,
//             limit
//         });

//     } catch (error) {
//         console.error("Error in autoFundRequestListGridData:", error);
//         return res.status(500).json({
//             success: false,
//             msg: "An error occurred while fetching data."
//         });
//     }
// };



const autoFundRequestListGridData = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const fields = [
            "user_name",
            "amount",
            "tx_request_number",
            "payment_method",
            "txn_ref",
            "reject_remark",
            "fund_payment_receipt",
            "deposit_type",
            "insert_date",
            "fund_status",
        ];

        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 1;
        const fieldIndex = req?.body?.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = req?.body?.order || -1;

        let searchValue = req?.body?.searchValue?.trim() || '';
        let searchQuery = {};

        // ADDED: Check for fund_status filter in request
        let statusFilter = {};
        if (req?.body?.fund_status !== undefined && req?.body?.fund_status !== null) {
            statusFilter = { fund_status: parseInt(req.body.fund_status) };
        }

        if (searchValue) {
            console.log("searchValue");
            const isNumeric = !isNaN(searchValue);
            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$fund_status" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$deposit_type" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { txn_ref: { $regex: `^${searchValue}`, $options: 'i' } },
                        { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
                        { payment_method: { $regex: `^${searchValue}`, $options: 'i' } },
                        { reject_remark: { $regex: `^${searchValue}`, $options: 'i' } },
                    ]
                };
            }
        }

        // Combine search and status filters
        const finalFilter = { ...searchQuery, ...statusFilter };

        // Count Total Filtered Data
        const totalDataAgg = await add_funds_module.aggregate([
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name",
                    amount: 1,
                    tx_request_number: 1,
                    reject_remark: 1,
                    deposit_type: 1,
                    payment_method: 1,
                    txn_ref: 1,
                    fund_status: 1,
                    insert_date: 1,
                    deposit_type: 1,
                    fund_payment_receipt: 1,
                    isAction: {
                        $cond: [
                            { $ne: ['$fund_status', 0] },
                            0,
                            1
                        ]
                    }
                }
            },
            { $match: finalFilter }, // CHANGED: Use combined filter
            { $count: "totalData" },
        ]);

        const totalData = totalDataAgg[0]?.totalData || 0;

        // Build Main Pipeline
        const pipeline = [
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile",
                    amount: 1,
                    tx_request_number: 1,
                    payment_method: 1,
                    txn_ref: 1,
                    reject_remark: 1,
                    fund_status: 1,
                    insert_date: 1,
                    deposit_type: 1,
                    fund_payment_receipt: 1,
                    isAction: {
                        $cond: [
                            { $ne: ['$fund_status', 0] },
                            0,
                            1
                        ]
                    }
                }
            },
            { $sort: { [orderField]: orderDir } },
            { $match: finalFilter }, // CHANGED: Use combined filter
        ];

        if (!searchValue) {
            pipeline.push({ $skip: (start - 1) * limit });
        }

        pipeline.push({ $limit: limit });

        const fundRequests = await add_funds_module.aggregate(pipeline);

        // Format Insert Date to IST
        const formattedFundRequests = fundRequests.map(v => ({
            ...v,
            insert_date: v.insert_date
                ? moment_timeZone(v.insert_date).tz("Asia/Kolkata").format("DD MMM YYYY, hh:mm:ss A")
                : "N/A",
            receipt_url: v?.fund_payment_receipt && baseUrl
                ? `${baseUrl}/file/uploads/images/${v.fund_payment_receipt}`
                : null
        }));

        return res.json({
            success: true,
            recordsFiltered: totalData,
            data: formattedFundRequests,
            limit
        });

    } catch (error) {
        console.error("Error in autoFundRequestListGridData:", error);
        return res.status(500).json({
            success: false,
            msg: "An error occurred while fetching data."
        });
    }
};



const acceptAutoFundRequest = async (req, res) => {
    const session = await mongoose.startSession();
    try {
        const depositDB_id = (req?.body?.depositDB_id || "").trim();
        const RefNo = (req?.body?.approveRefNo || "").trim();

        console.log("auto fund req body-", req.body)
        let refData = {}

        if (RefNo) {
            refData = await add_funds_module.findOne({ txn_ref: RefNo });

            console.log("refData-", refData)
            if (!refData) {
                return res.status(200).json({ success: false, msg: "Please Enter a valid Ref. No..." })
            }
            console.log(refData.userDB_id, "ref id -", depositDB_id)

            if (refData && refData.userDB_id != depositDB_id) {
                return res.status(200).json({ success: false, msg: "Reference no already in used," })
            }
        }
        else {
            return res.status(404).json({ success: false, msg: "Ref. No Must be required !" })
        }




        if (!mongoose.isValidObjectId(depositDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid request ID" });
        }

        let responseData;

        await session.withTransaction(async () => {
            const request = await add_funds_module.findById(refData._id).populate('userDB_id').session(session);
            if (!request) {
                throw new Error("Request not found");
            }

            console.log(`(((((((()))))) ~ server/controllers/adminController.js:875 ~ awaitsessionwithTransactionasync ~ request:`, request);

            request.fund_status = 1;
            const before_wallet_amount = request?.userDB_id?.wallet_balance;
            const emitWallet = request?.userDB_id?.wallet_balance ? request?.userDB_id?.wallet_balance + request.amount : request.amount
            request.userDB_id.wallet_balance = request?.userDB_id?.wallet_balance ? request?.userDB_id?.wallet_balance + request.amount : request.amount

            console.log(`(((((((()))))) ~ server/controllers/adminController.js:878 ~ awaitsessionwithTransactionasync ~ emitWallet:`, emitWallet);
            // if(emitWallet == (request?.userDB_id?.wallet_balance + request.amount) ){
            //     console.log("action emit");
            emitToUser(request?.userDB_id?._id?.toString(), "wallet_update", "wallet update");

            // }

            console.log(`(((((((()))))) ~ server/controllers/adminController.js:875 ~ awaitsessionwithTransactionasync ~ New request:`, request);

            await request.userDB_id.save({ session });
            await request.save({ session });

            const history = {
                userDB_id: request.userDB_id,
                amount: request.amount,
                transaction_type: 1,
                before_wallet: before_wallet_amount,
                transaction_note: `Auto Deposit Request No.${request.tx_request_number} Processed`,
                amount_status: 19,
                tx_request_number: request.tx_request_number,
            };

            await wallet_trans_history_module.create([history], { session });

            responseData = {
                success: true,
                request_status: "Accepted",
                msg: "Request Successfully Accepted"
            };
        });

        return res.json(responseData);

    } catch (error) {
        console.error("Error in acceptAutoFundRequest:", error);
        return res.status(500).json({ success: false, msg: error.message || "Server error" });
    } finally {
        session.endSession();
    }
};

const rejectAutoFundRequest = async (req, res) => {
    try {
        const depositDB_id = (req?.body?.depositDB_id || "").trim();
        const reject_remark = (req?.body?.reject_remark || "").trim();

        if (!mongoose.isValidObjectId(depositDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid request ID" });
        }

        if (!reject_remark) {
            return res.status(400).json({ success: false, msg: "Reject remark is required" });
        }

        const request = await add_funds_module.findById(depositDB_id).populate('userDB_id');
        if (!request) {
            return res.status(404).json({ success: false, msg: "Request not found" });
        }

        if (request.fund_status !== 0) {
            return res.status(400).json({ success: false, msg: "Request already processed" });
        }

        request.fund_status = 2
        request.reject_remark = reject_remark
        request.userDB_id.last_update = getISTDateObject() || 0;

        await request.userDB_id.save();
        await request.save()
        return res.json({
            success: true,
            request_status: "Rejected",
            msg: "Request Successfully Rejected"
        });

    } catch (err) {
        console.error("Error in rejectAutoFundRequest:", err);
        return res.status(500).json({ success: false, msg: "Server error" });
    }
};

const deleteAutoFundRequest = async (req, res) => {
    try {
        const depositDB_id = (req?.body?.depositDB_id || "").trim();

        if (!mongoose.isValidObjectId(depositDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid request ID" });
        }

        const result = await add_funds_module.deleteOne({ _id: depositDB_id });

        if (result?.deletedCount === 0) {
            return res.json({ success: false, msg: "Request not found or already deleted" });
        }

        return res.json({
            success: true,
            msg: "Successfully Deleted"
        });
    } catch (err) {
        console.error("Error in deleteAutoRequestDepo:", err);
        res.status(500).json({ success: false, msg: "Server error" });
    }
};

const getDashboardWithdrawReportDetails = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const fields = [
            "user_name",
            "amount",
            "tx_request_number",
            "payment_method",
            "remark",
            "fund_payment_receipt",
            "withdraw_type",
            "insert_date",
            "fund_status",
        ];

        // console.log(`(((((((()))))) ~ adminController.js:1214 ~ getDashboardWithdrawReportDetails ~ req.body:`, req.body);

        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) - 1 || 0;
        let searchValue = req?.body?.searchValue?.trim() || '';
        const fieldIndex = req?.body?.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = req?.body?.order || -1;
        const status = req?.body?.fund_status;
        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            if (isNumeric) {
                searchQuery = {
                    $or: [
                        { $expr: { $regexMatch: { input: { $toString: "$amount" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$fund_status" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$payment_method" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$withdraw_type" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$ac_number" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$paytm_number" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$google_pay_number" }, regex: `^${searchValue}`, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$phone_pay_number" }, regex: `^${searchValue}`, options: "i" } } },
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { remark: { $regex: `^${searchValue}`, $options: 'i' } },
                        { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
                        { bank_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { branch_address: { $regex: `^${searchValue}`, $options: 'i' } },
                        { ac_holder_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { ifsc_code: { $regex: `^${searchValue}`, $options: 'i' } },
                    ]
                };
            }
        }

        const paginatedData_pipeline = [];
        if (!searchValue) {
            paginatedData_pipeline.push({ $skip: start * limit });
        }
        paginatedData_pipeline.push({ $limit: limit });

        const withoutPaginated_pipeline = [
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            { $unwind: '$userData' },
            { $match: { fund_status: req?.body?.fund_status } },
            { $sort: { [orderField]: orderDir === 1 ? 1 : -1 } },
            {
                $project: {
                    user_name: '$userData.user_name',
                    userDB_id: '$userData._id',
                    wallet_balance: '$userData.wallet_balance',
                    mobile: '$userData.mobile',
                    fund_payment_receipt: 1,
                    fund_status: "$fund_status",
                    remark: 1,
                    payment_method: 1,
                    tx_request_number: 1,
                    amount: 1,
                    withdraw_type: 1,
                    insert_date: 1,
                    paytm_number: 1,
                    ac_holder_name: 1,
                    ac_number: 1,
                    google_pay_number: 1,
                    phone_pay_number: 1,
                    isAction: {
                        $cond: [
                            { $in: ["$fund_status", [1, 2]] },
                            0,
                            1
                        ]
                    }
                }
            },
            { $match: searchQuery },
        ];

        const totalData = await withdraw_fund_request_module.aggregate([
            ...withoutPaginated_pipeline,
            ...paginatedData_pipeline
        ]);
        console.log("kjdfkjdfkldj", totalData)

        const countResult = await withdraw_fund_request_module.aggregate([
            ...withoutPaginated_pipeline,
            { $count: "total" }
        ]);

        const totalFiltered = countResult?.[0]?.total || 0;

        // console.log("totalData",totalData)

        // Get transaction summary for each user
        const dataWithTransactionSummary = await Promise.all(
            totalData.map(async (rs) => {
                // let method = '';
                // if (rs.payment_method === 1) {
                //     method = `A/c Transfer (${rs.ac_number})(${rs.ac_holder_name})`;
                // } else if (rs.payment_method === 2) {
                //     method = `Paytm (${rs.paytm_number})`;
                // } else if (rs.payment_method === 3) {
                //     method = `Google Pay (${rs.google_pay_number})`;
                // } else if (rs.payment_method === 4) {
                //     method = `PhonePay (${rs.phone_pay_number})`;
                // }

                // Get transaction summary for this user
                const transactionSummary = await userTotalAddFundAndWithdrawFundAmount(rs.userDB_id.toString());

                return {
                    ...rs,
                    insert_date: rs.insert_date
                        ? moment_timeZone(rs.insert_date).tz("Asia/Kolkata").format("DD MMM YYYY, hh:mm A")
                        : "N/A",
                    receipt_url: rs?.fund_payment_receipt && baseUrl
                        ? `${baseUrl}/file/uploads/images/${rs.fund_payment_receipt}`
                        : null,
                    transactionSummary: transactionSummary.success ? {
                        totalDeposit: transactionSummary.totalDeposit,
                        totalWithdrawal: transactionSummary.totalWithdrawal,
                        netBalance: transactionSummary.netBalance
                    } : null
                };
            })
        );

        // return res.json({
        //     success: true,
        //     msg: "Withdraw request list fetched successfully",
        //     recordsFiltered: totalFiltered,
        //     data,
        //     limit
        // });
        return res.json({
            success: true,
            msg: "Withdraw request list fetched successfully",
            recordsFiltered: totalFiltered,
            data: dataWithTransactionSummary,
            limit
        });

    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: "Server error" });
    }
};

// pending for payment getway automatic
const viewWithdrawRequest = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const withdraw_requestDB_id = req.params.withdrawDB_id || req.url.split('/')[3];

        let withdrawRequestData = await withdraw_fund_request_module.aggregate([
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            {
                $lookup: {
                    from: 'wallet_trans_histories',
                    localField: 'tx_request_number',
                    foreignField: 'tx_request_number',
                    as: 'tx_info'
                }
            },
            { $unwind: { path: '$userData', preserveNullAndEmptyArrays: true } },
            { $unwind: { path: '$tx_info', preserveNullAndEmptyArrays: true } },
            {
                $project: {
                    fund_payment_receipt: 1,
                    fund_status: 1,
                    remark: 1,
                    payment_method: 1,
                    tx_request_number: 1,
                    amount: 1,
                    withdraw_type: 1,
                    insert_date: 1,
                    paytm_number: 1,
                    ac_holder_name: 1,
                    ac_number: 1,
                    google_pay_number: 1,
                    phone_pay_number: 1,
                    bank_name: 1,
                    branch_address: 1,
                    ifsc_code: 1,
                    user_name: '$userData.user_name',
                    accepte_date: '$tx_info.insert_date',
                    withdraw_requestDB_id: 1,
                    userDB_id: 1,
                }
            },
            { $match: { _id: new mongoose.Types.ObjectId(withdraw_requestDB_id) } }
        ]);

        console.log(withdrawRequestData)

        withdrawRequestData = withdrawRequestData.map(value => {
            const formatIST = (date) =>
                date ? moment_timeZone(date).tz('Asia/Kolkata').format('DD MMM YYYY, hh:mm:ss A') : null;

            return {
                ...value,
                insert_date: formatIST(value.insert_date),
                accepte_date: formatIST(value.accepte_date),
                receipt_url: value?.fund_payment_receipt && baseUrl
                    ? `${baseUrl}/file/uploads/images/${value.fund_payment_receipt}`
                    : null
            };
        });

        return res.json({
            success: true,
            withdrawRequestData
        });
    } catch (err) {
        console.error(err);
        res.status(500).json({ success: false, msg: "Server error" });
    }
};

// const approveWithdrawRequest = async (req, res) => {
//     const session = await mongoose.startSession();
//     session.startTransaction();

//     try {
//         const { withdraw_reqDB_id = "", remark = "" } = req.body || {};

//         if (!withdraw_reqDB_id || !remark) {
//             return res.status(400).json({ success: false, msg: 'withdraw_reqDB_id and remark are required' });
//         }

//         if (!mongoose.isValidObjectId(withdraw_reqDB_id)) {
//             return res.status(400).json({ success: false, msg: 'Invalid withdraw_reqDB_id' });
//         }

//         if (!req.file || !req.file.buffer || !req.file.mimetype) {
//             return res.status(400).json({ success: false, msg: 'Valid file is required (jpeg/jpg/png)' });
//         }

//         // Save the payment receipt image
//         const image = new file_module({
//             fileInfo: {
//                 fileBuffer: req.file.buffer,
//                 content_type: req.file.mimetype
//             }
//         });

//         const savedImage = await image.save({ session });

//         // Update withdraw request
//         const withdrawUpdate = await withdraw_fund_request_module.findByIdAndUpdate(
//             withdraw_reqDB_id,
//             {
//                 fund_status: 1, // Accepted
//                 fund_payment_receipt: savedImage._id,
//                 remark: remark
//             },
//             { new: true, session }
//         ).populate('userDB_id');

//         if (!withdrawUpdate) {
//             await session.abortTransaction();
//             return res.status(404).json({ success: false, msg: 'Withdraw request not found.' });
//         }

//         const { userDB_id, amount, tx_request_number } = withdrawUpdate;

//         userDB_id.wallet_balance -= Number(amount);
//         await userDB_id.save({ session });

//         // Insert wallet transaction history
//         await wallet_trans_history_module.create([{
//             userDB_id: userDB_id._id,
//             amount: amount,
//             transaction_type: 2, // Debit
//             transaction_note: 'Amount Withdraw',
//             amount_status: 2,
//             tx_request_number
//         }], { session });

//         // Notify user
//         await user_notification_module.create([{
//             userDB_id: userDB_id._id,
//             msg: `Congratulations, your withdraw request of amount â‚¹${amount} has been accepted.`
//         }], { session });

//         await session.commitTransaction();
//         session.endSession();

//         return res.json({
//             success: true,
//             request_status: 'Accepted',
//             msg: 'Withdraw Request Approved successfully.'
//         });

//     } catch (error) {
//         await session.abortTransaction();
//         session.endSession();
//         console.error('Approve Withdraw Request Error:', error);
//         return res.status(500).json({ success: false, msg: 'Internal Server Error' });
//     }
// };





// const approveWithdrawRequest = async (req, res) => {
//     const session = await mongoose.startSession();
//     session.startTransaction();

//     try {
//         const { withdraw_reqDB_id = "", remark = "" } = req.body || {};

//         if (!withdraw_reqDB_id || !remark) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'withdraw_reqDB_id and remark are required' });
//         }

//         if (!mongoose.isValidObjectId(withdraw_reqDB_id)) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'Invalid withdraw_reqDB_id' });
//         }

//         // Check if file exists (using the new storage configuration)
//         if (!req.file) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'Payment receipt file is required' });
//         }

//         // Find the withdraw request first to check its current status
//         const withdrawRequest = await withdraw_fund_request_module
//             .findById(withdraw_reqDB_id)
//             .populate('userDB_id')
//             .session(session);

//         if (!withdrawRequest) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({ success: false, msg: 'Withdraw request not found.' });
//         }

//         // Check if request is already processed
//         if (withdrawRequest.fund_status !== 0) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ 
//                 success: false, 
//                 msg: `Withdraw request has already been ${withdrawRequest.fund_status === 1 ? 'approved' : 'rejected'}.` 
//             });
//         }

//         // Check if user has sufficient balance
//         if (withdrawRequest.userDB_id.wallet_balance < withdrawRequest.amount) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ 
//                 success: false, 
//                 msg: 'User has insufficient balance for this withdrawal.' 
//             });
//         }

//         // Save the payment receipt image (using file path instead of buffer)
//         const image = new file_module({
//             fileInfo: {
//                 // Since we're now using disk storage, we need to store the file path
//                 // Adjust this based on your file_module schema
//                 filename: req.file.filename,
//                 originalName: req.file.originalname,
//                 path: req.file.path,
//                 content_type: req.file.mimetype,
//                 size: req.file.size
//             }
//         });

//         const savedImage = await image.save({ session });

//         // Update withdraw request
//         const withdrawUpdate = await withdraw_fund_request_module.findByIdAndUpdate(
//             withdraw_reqDB_id,
//             {
//                 fund_status: 1, // Accepted
//                 fund_payment_receipt: savedImage._id,
//                 remark: remark
//             },
//             { new: true, session }
//         ).populate('userDB_id');

//         // Deduct amount from user's wallet
//         withdrawUpdate.userDB_id.wallet_balance -= Number(withdrawUpdate.amount);
//         await withdrawUpdate.userDB_id.save({ session });

//         // Insert wallet transaction history
//         await wallet_trans_history_module.create([{
//             userDB_id: withdrawUpdate.userDB_id._id,
//             amount: withdrawUpdate.amount,
//             transaction_type: 2, // Debit
//             transaction_note: 'Amount Withdraw',
//             amount_status: 2, // amount withdraw by admin
//             tx_request_number: withdrawUpdate.tx_request_number
//         }], { session });

//         // Notify user
//         await user_notification_module.create([{
//             userDB_id: withdrawUpdate.userDB_id._id,
//             msg: `Congratulations, your withdraw request of amount â‚¹${withdrawUpdate.amount} has been accepted.`
//         }], { session });

//         await session.commitTransaction();
//         session.endSession();

//         return res.json({
//             success: true,
//             request_status: 'Accepted',
//             msg: 'Withdraw Request Approved successfully.'
//         });

//     } catch (error) {
//         // Handle specific errors
//         if (session.inTransaction()) {
//             await session.abortTransaction();
//         }
//         session.endSession();

//         console.error('Approve Withdraw Request Error:', error);

//         if (error.name === 'ValidationError') {
//             return res.status(400).json({ success: false, msg: 'Validation Error: ' + error.message });
//         }

//         return res.status(500).json({ success: false, msg: 'Internal Server Error' });
//     }
// };


// const approveWithdrawRequest = async (req, res) => {
//     const session = await mongoose.startSession();
//     session.startTransaction();

//     try {
//         const { withdraw_reqDB_id = "", remark = "" } = req.body || {};

//         if (!withdraw_reqDB_id || !remark) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'withdraw_reqDB_id and remark are required' });
//         }

//         if (!mongoose.isValidObjectId(withdraw_reqDB_id)) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'Invalid withdraw_reqDB_id' });
//         }

//         // Check if file exists
//         if (!req.file) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'Payment receipt file is required' });
//         }

//         // Find the withdraw request first to check its current status
//         const withdrawRequest = await withdraw_fund_request_module
//             .findById(withdraw_reqDB_id)
//             .populate('userDB_id')
//             .session(session);

//         if (!withdrawRequest) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ success: false, msg: 'Withdraw request not found.' });
//         }

//         // Check if request is already processed
//         if (withdrawRequest.fund_status !== 0) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ 
//                 success: false, 
//                 msg: `Withdraw request has already been ${withdrawRequest.fund_status === 1 ? 'approved' : 'rejected'}.` 
//             });
//         }

//         // Check if user has sufficient balance
//         if (withdrawRequest.userDB_id.wallet_balance < withdrawRequest.amount) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({ 
//                 success: false, 
//                 msg: 'User has insufficient balance for this withdrawal.' 
//             });
//         }

//         // Update withdraw request with file path/name (not using file_module)
//         const withdrawUpdate = await withdraw_fund_request_module.findByIdAndUpdate(
//             withdraw_reqDB_id,
//             {
//                 fund_status: 1, // Accepted
//                 fund_payment_receipt: req.file.filename, // Store just the filename
//                 remark: remark
//             },
//             { new: true, session }
//         ).populate('userDB_id');

//         // Deduct amount from user's wallet
//         withdrawUpdate.userDB_id.wallet_balance -= Number(withdrawUpdate.amount);
//         await withdrawUpdate.userDB_id.save({ session });

//         // Insert wallet transaction history
//         await wallet_trans_history_module.create([{
//             userDB_id: withdrawUpdate.userDB_id._id,
//             amount: withdrawUpdate.amount,
//             transaction_type: 2, // Debit
//             transaction_note: 'Amount Withdraw',
//             amount_status: 2, // amount withdraw by admin
//             tx_request_number: withdrawUpdate.tx_request_number
//         }], { session });

//         // Notify user
//         await user_notification_module.create([{
//             userDB_id: withdrawUpdate.userDB_id._id,
//             msg: `Congratulations, your withdraw request of amount â‚¹${withdrawUpdate.amount} has been accepted.`
//         }], { session });

//         await session.commitTransaction();
//         session.endSession();

//         return res.json({
//             success: true,
//             request_status: 'Accepted',
//             msg: 'Withdraw Request Approved successfully.'
//         });

//     } catch (error) {
//         // Handle specific errors
//         if (session.inTransaction()) {
//             await session.abortTransaction();
//         }
//         session.endSession();

//         console.error('Approve Withdraw Request Error:', error);

//         if (error.name === 'ValidationError') {
//             return res.status(400).json({ success: false, msg: 'Validation Error: ' + error.message });
//         }

//         return res.status(500).json({ success: false, msg: 'Internal Server Error' });
//     }
// };


const approveWithdrawRequest = async (req, res) => {
    try {
        const { withdraw_reqDB_id = "", remark = "", ids = [], payment_method = "", action = 1 } = req.body || {};
        console.log("req.body approve with draw list req", req.body)
        const isBulk = Array.isArray(ids) && ids.length > 0;
        const isApprove = action === 1; // 1 = approve, 2 = reject

        // Validate inputs
        if ((!withdraw_reqDB_id && !isBulk) || !remark) {
            return res.status(400).json({
                success: false,
                msg: isBulk ? 'remark is required for bulk action' : 'withdraw_reqDB_id and remark are required'
            });
        }
        console.log("req", req.admin)

        // Prepare IDs to process
        const requestIds = isBulk ? ids : [withdraw_reqDB_id];

        // Validate all IDs
        const invalidIds = requestIds.filter(id => !mongoose.isValidObjectId(id));
        if (invalidIds.length > 0) {
            return res.status(400).json({
                success: false,
                msg: `Invalid withdraw_reqDB_id(s): ${invalidIds.join(', ')}`
            });
        }

        // Find all withdraw requests
        const withdrawRequests = await withdraw_fund_request_module
            .find({ _id: { $in: requestIds } })
            .populate('userDB_id');

        if (withdrawRequests.length === 0) {
            return res.status(400).json({ success: false, msg: 'No withdraw requests found.' });
        }

        // Process all requests
        const processedRequests = [];
        const notificationPromises = [];
        const walletHistoryPromises = [];

        for (const withdrawRequest of withdrawRequests) {
            // Update withdraw request status only
            const updateData = {
                fund_status: isApprove ? 1 : 2, // 1 = Approved, 2 = Rejected
                remark: remark,
            };

            // Only add payment method and receipt for approvals
            if (isApprove) {
                updateData.payment_method = payment_method || withdrawRequest.payment_method;

                // Add receipt only for single approval
                if (!isBulk && req.file) {
                    updateData.fund_payment_receipt = req.file.filename;
                }
            }

            const updatedRequest = await withdraw_fund_request_module.findByIdAndUpdate(
                withdrawRequest._id,
                updateData,
                { new: true }
            ).populate('userDB_id');

            // ONLY FOR APPROVALS: Deduct amount from user's wallet
            if (isApprove) {
                // Check for insufficient balance
                let beforeWallet = '';
                if (updatedRequest.userDB_id.wallet_balance < Number(updatedRequest.amount)) {
                    beforeWallet = updatedRequest.userDB_id.wallet_balance;
                    return res.status(400).json({
                        success: false,
                        msg: `Insufficient balance for user ${updatedRequest.userDB_id.name}. Requested: ${updatedRequest.amount}, Available: ${updatedRequest.userDB_id.wallet_balance}`
                    });
                }

                updatedRequest.userDB_id.wallet_balance -= Number(updatedRequest.amount);
                await updatedRequest.userDB_id.save();

                // Prepare wallet transaction history for approval
                walletHistoryPromises.push(
                    wallet_trans_history_module.create([{
                        userDB_id: updatedRequest.userDB_id._id,
                        amount: updatedRequest.amount,
                        admin_name: req?.admin?.full_name || '',
                        admin_type: req?.admin?.admin_type || '',
                        before_Wallet: beforeWallet,
                        transaction_type: payment_method || '',
                        transaction_note: 'Amount Withdraw',
                        amount_status: 2, // amount withdraw by admin
                        tx_request_number: updatedRequest.tx_request_number
                    }])
                );
            }

            // Prepare user notification based on action
            const notificationMsg = isApprove
                ? `Congratulations, your withdraw request of amount â‚¹${updatedRequest.amount} has been accepted.`
                : `Your withdraw request of amount â‚¹${updatedRequest.amount} has been rejected. Reason: ${remark}`;

            notificationPromises.push(
                user_notification_module.create([{
                    userDB_id: updatedRequest.userDB_id._id,
                    msg: notificationMsg
                }])
            );

            processedRequests.push(updatedRequest);
        }

        // Execute all promises
        await Promise.all([...walletHistoryPromises, ...notificationPromises]);

        return res.json({
            success: true,
            request_status: isApprove ? 'Accepted' : 'Rejected',
            msg: isBulk
                ? `${processedRequests.length} withdraw requests ${isApprove ? 'approved' : 'rejected'} successfully.`
                : `Withdraw Request ${isApprove ? 'Approved' : 'Rejected'} successfully.`,
            processedCount: processedRequests.length,
            processedIds: processedRequests.map(req => req._id)
        });

    } catch (error) {
        console.error('Approve/Reject Withdraw Request Error:', error);

        if (error.name === 'ValidationError') {
            return res.status(400).json({ success: false, msg: 'Validation Error: ' + error.message });
        }

        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};





// const approveWithdrawRequest = async (req, res) => {
//     // const session = await mongoose.startSession();
//     // session.startTransaction();

//     try {
//         const { withdraw_reqDB_id = "", remark = "", ids = [], payment_method = "" } = req.body || {};
//         const isBulk = Array.isArray(ids) && ids.length > 0;

//         // Validate inputs
//         if ((!withdraw_reqDB_id && !isBulk) || !remark) {
//             // await session.abortTransaction();
//             return res.status(400).json({
//                 success: false,
//                 msg: isBulk ? 'remark is required for bulk approval' : 'withdraw_reqDB_id and remark are required'
//             });
//         }

//         // Check if file exists (for single approval)
//         // if (!isBulk && !req.file) {
//         //     // await session.abortTransaction();
//         //     // session.endSession();
//         //     return res.status(400).json({ success: false, msg: 'Payment receipt file is required' });
//         // }

//         // Prepare IDs to process
//         const requestIds = isBulk ? ids : [withdraw_reqDB_id];

//         // Validate all IDs
//         const invalidIds = requestIds.filter(id => !mongoose.isValidObjectId(id));
//         if (invalidIds.length > 0) {
//             // await session.abortTransaction();
//             // session.endSession();
//             return res.status(400).json({
//                 success: false,
//                 msg: `Invalid withdraw_reqDB_id(s): ${invalidIds.join(', ')}`
//             });
//         }

//         // Find all withdraw requests
//         const withdrawRequests = await withdraw_fund_request_module
//             .find({ _id: { $in: requestIds } })
//             .populate('userDB_id');
//             // .session(session);

//         if (withdrawRequests.length === 0) {
//             // await session.abortTransaction();
//             // session.endSession();
//             return res.status(400).json({ success: false, msg: 'No withdraw requests found.' });
//         }

//         // Check for already processed requests
//         const alreadyProcessed = withdrawRequests.filter(req => req.fund_status == 3);
//         // if (alreadyProcessed.length > 0) {
//         //     // await session.abortTransaction();
//         //     // session.endSession();
//         //     return res.status(400).json({
//         //         success: false,
//         //         msg: `${alreadyProcessed.length} request(s) have already been processed.`,
//         //         processedRequests: alreadyProcessed.map(req => ({
//         //             id: req._id,
//         //             status: req.fund_status === 1 ? 'approved' : 'rejected'
//         //         }))
//         //     });
//         // }

//         // Check for insufficient balances
//         const insufficientBalanceRequests = withdrawRequests.filter(
//             req => req.userDB_id.wallet_balance < req.amount
//         );

//         if (insufficientBalanceRequests.length > 0) {
//             // await session.abortTransaction();
//             // session.endSession();
//             return res.status(400).json({
//                 success: false,
//                 msg: `${insufficientBalanceRequests.length} user(s) have insufficient balance for withdrawal.`,
//                 insufficientBalanceRequests: insufficientBalanceRequests.map(req => ({
//                     id: req._id,
//                     userId: req.userDB_id._id,
//                     userName: req.userDB_id.name,
//                     requestedAmount: req.amount,
//                     availableBalance: req.userDB_id.wallet_balance
//                 }))
//             });
//         }

//         // Process all requests
//         const processedRequests = [];
//         const notificationPromises = [];
//         const walletHistoryPromises = [];

//         for (const withdrawRequest of withdrawRequests) {
//             // Update withdraw request
//             const updateData = {
//                 fund_status: 1, // Accepted
//                 remark: remark,
//                 payment_method: payment_method || withdrawRequest.payment_method
//             };

//             // Add receipt only for single approval (bulk might not have individual receipts)
//             if (!isBulk && req.file) {
//                 updateData.fund_payment_receipt = req.file.filename;
//             }

//             const updatedRequest = await withdraw_fund_request_module.findByIdAndUpdate(
//                 withdrawRequest._id,
//                 updateData,
//                 { new: true}
//             ).populate('userDB_id');

//             // Deduct amount from user's wallet
//             updatedRequest.userDB_id.wallet_balance -= Number(updatedRequest.amount);
//             await updatedRequest.userDB_id.save();

//             // Prepare wallet transaction history
//             walletHistoryPromises.push(
//                 wallet_trans_history_module.create([{
//                     userDB_id: updatedRequest.userDB_id._id,
//                     amount: updatedRequest.amount,
//                     transaction_type: 2, // Debit
//                     transaction_note: 'Amount Withdraw',
//                     amount_status: 2, // amount withdraw by admin
//                     tx_request_number: updatedRequest.tx_request_number
//                 }])
//             );

//             // Prepare user notification
//             notificationPromises.push(
//                 user_notification_module.create([{
//                     userDB_id: updatedRequest.userDB_id._id,
//                     msg: `Congratulations, your withdraw request of amount â‚¹${updatedRequest.amount} has been accepted.`
//                 }])
//             );

//             processedRequests.push(updatedRequest);
//         }

//         // Execute all promises
//         await Promise.all([...walletHistoryPromises, ...notificationPromises]);

//         // await session.commitTransaction();
//         // session.endSession();

//         return res.json({
//             success: true,
//             request_status: 'Accepted',
//             msg: isBulk
//                 ? `${processedRequests.length} withdraw requests approved successfully.`
//                 : 'Withdraw Request Approved successfully.',
//             processedCount: processedRequests.length,
//             processedIds: processedRequests.map(req => req._id)
//         });

//     } catch (error) {
//         // Handle specific errors
//         // if (session.inTransaction()) {
//         //     await session.abortTransaction();
//         // }
//         // session.endSession();

//         console.error('Approve Withdraw Request Error:', error);

//         if (error.name === 'ValidationError') {
//             return res.status(400).json({ success: false, msg: 'Validation Error: ' + error.message });
//         }

//         return res.status(500).json({ success: false, msg: 'Internal Server Error' });
//     }
// };


const moveWithdrawToProcessing = async (req, res) => {
    try {
        const { withdraw_reqDB_id, ids, remark } = req.body;

        if (!withdraw_reqDB_id && (!ids || ids.length === 0)) {
            return res.status(400).json({ success: false, msg: "No request ID(s) provided" });
        }

        const update = {
            fund_status: 3, // Processing
            remark: remark || "Moved to processing",
            update_date: new Date()
        };

        let result;
        if (withdraw_reqDB_id) {
            result = await withdraw_fund_request_module.findByIdAndUpdate(
                withdraw_reqDB_id,
                update,
                { new: true }
            );
        } else {
            result = await withdraw_fund_request_module.updateMany(
                { _id: { $in: ids } },
                { $set: update }
            );
        }

        return res.json({
            success: true,
            msg: "Withdraw request(s) moved to processing",
            data: result
        });

    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: "Server error" });
    }
};




const rejectWithdrawRequest = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { withdraw_reqDB_id = "", remark = "" } = req.body || {};

        // Validate required fields
        if (!withdraw_reqDB_id || !remark.trim()) {
            return res.status(400).json({
                success: false,
                msg: 'withdraw_reqDB_id and remark are required.'
            });
        }

        // Validate MongoDB ObjectId
        if (!mongoose.isValidObjectId(withdraw_reqDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid withdraw_reqDB_id.'
            });
        }

        // Fetch withdraw request
        const withdrawRequest = await withdraw_fund_request_module.findById(withdraw_reqDB_id).session(session);
        if (!withdrawRequest) {
            await session.abortTransaction();
            return res.status(404).json({
                success: false,
                msg: 'Withdraw request not found.'
            });
        }

        // Check if already rejected
        if (withdrawRequest.fund_status === 2) {
            await session.abortTransaction();
            return res.status(409).json({
                success: false,
                msg: 'Withdraw request is already rejected.'
            });
        }

        // Update status
        withdrawRequest.fund_status = 2; // 2 = rejected
        withdrawRequest.remark = remark;

        await withdrawRequest.save({ session });

        // Notify user
        await user_notification_module.create([{
            userDB_id: withdrawRequest.userDB_id,
            msg: `Sorry, your withdraw request of â‚¹${withdrawRequest.amount} has been rejected.`,
        }], { session });

        // Commit transaction
        await session.commitTransaction();
        session.endSession();

        return res.json({
            success: true,
            request_status: 'Rejected',
            msg: 'Withdraw request rejected successfully.'
        });

    } catch (error) {
        console.error('Error rejecting withdraw request:', error);
        await session.abortTransaction();
        session.endSession();

        return res.status(500).json({
            success: false,
            msg: 'Internal Server Error'
        });
    }
};

const reprocessWithdrawRequest = async (req, res) => {
    try {
        const { withdraw_reqDB_id = "", ids = [] } = req.body || {};
        const isBulk = Array.isArray(ids) && ids.length > 0;

        // Validate inputs
        if (!withdraw_reqDB_id && !isBulk) {
            return res.status(400).json({
                success: false,
                msg: 'withdraw_reqDB_id or ids array is required'
            });
        }

        // Prepare IDs to process
        const requestIds = isBulk ? ids : [withdraw_reqDB_id];

        // Validate all IDs
        const invalidIds = requestIds.filter(id => !mongoose.isValidObjectId(id));
        if (invalidIds.length > 0) {
            return res.status(400).json({
                success: false,
                msg: `Invalid withdraw_reqDB_id(s): ${invalidIds.join(', ')}`
            });
        }

        // Find all withdraw requests that are currently failed (status 2)
        const withdrawRequests = await withdraw_fund_request_module
            .find({
                _id: { $in: requestIds },
                fund_status: 2 // Only reprocess failed requests
            })
            .populate('userDB_id');

        if (withdrawRequests.length === 0) {
            return res.status(400).json({
                success: false,
                msg: 'No failed withdraw requests found to reprocess.'
            });
        }

        // Update status to Processing (3)
        const updatedRequests = await withdraw_fund_request_module.updateMany(
            { _id: { $in: withdrawRequests.map(req => req._id) } },
            {
                fund_status: 3, // Processing
                remark: "Request reprocessed and moved to processing"
            }
        );

        // Create notifications
        const notificationPromises = withdrawRequests.map(req =>
            user_notification_module.create([{
                userDB_id: req.userDB_id._id,
                msg: `Your failed withdraw request of amount â‚¹${req.amount} has been reprocessed and is now in processing.`
            }])
        );

        await Promise.all(notificationPromises);

        return res.json({
            success: true,
            msg: isBulk
                ? `${withdrawRequests.length} failed requests moved to processing successfully.`
                : 'Failed request moved to processing successfully.',
            reprocessedCount: withdrawRequests.length,
            reprocessedIds: withdrawRequests.map(req => req._id)
        });

    } catch (error) {
        console.error('Reprocess Withdraw Request Error:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};



const getMainSettings = async (req, res) => {
    try {
        const [app_link, admin_bank_detail, all_fix_values_raw] = await Promise.all([
            app_link_module.findOne(),
            admin_bank_detail_module.findOne(),
            fix_values_module.findOne().lean()
        ]);

        if (!all_fix_values_raw) {
            return res.status(404).json({
                success: false,
                msg: 'Fix values not found',
            });
        }

        const formatTime_IST = (time) => {
            return moment_timeZone(time).tz("Asia/Kolkata").format("HH:mm");
        };

        const all_fix_values = {
            ...all_fix_values_raw,
            withdraw_open_time: formatTime_IST(all_fix_values_raw?.withdraw_open_time),
            withdraw_close_time: formatTime_IST(all_fix_values_raw?.withdraw_close_time),
        };

        res.json({
            success: true,
            data: {
                app_link,
                admin_bank_detail,
                all_fix_values,
            },
        });

    } catch (error) {
        console.error('Error in getMainSettings:', error.message || error);
        res.status(500).json({
            success: false,
            msg: 'Internal Server Error',
        });
    }
};

const addAppLink = async (req, res) => {
    try {
        const app_link = toStr(req?.body?.app_link)?.trim();
        const content = toStr(req?.body?.content)?.trim();

        if (!app_link || !content) {
            return res.status(400).json({
                success: false,
                msg: 'App link and content are required.',
            });
        }

        const appData = { app_link, content };

        await app_link_module.findOneAndUpdate({}, appData, { upsert: true });

        return res.json({
            success: true,
            msg: 'App Link Successfully Updated.',
        });
    } catch (err) {
        console.error('Error in addAppLink:', err);
        return res.status(500).json({
            success: false,
            msg: 'Something went wrong. Please try again.',
        });
    }
};

const addAdminUpiDetail = async (req, res) => {
    try {
        const {
            google_upi_payment_id = '',
            phonepay_upi_payment_id = '',
            upi_payment_id = '',
            status = '',
            ac_holder_name = '',
            account_number = '',
            ifsc_code = ''
        } = req.body || {};

        const updateFields = {
            google_upi_payment_id,
            phonepay_upi_payment_id,
            upi_payment_id,
            status,
            ac_holder_name,
            account_number,
            ifsc_code,
        };

        await admin_bank_detail_module.findOneAndUpdate(
            {},
            { $set: updateFields },
            { upsert: true, new: true }
        );

        return res.json({
            success: true,
            msg: 'Bank/UPI details updated successfully.'
        });
    } catch (error) {
        console.error('Error in addAdminUpiDetail:', error);
        return res.status(500).json({ success: false, msg: 'Server error. Please try again later.' });
    }
};

const addAdminFixValues_with_maintainence = async (req, res) => {
    try {
        let all_fix_values = req?.body || {};

        // Get current date in IST
        const todayIST = moment_timeZone().tz('Asia/Kolkata');
        const todayStr = todayIST.format("YYYY-MM-DD"); // e.g., "2025-07-11"

        const parseTimeToIST = (timeStr) => {
            if (!timeStr) return null;
            const [hh, mm] = timeStr.split(":");
            // Create full IST datetime using moment-timezone
            const istMoment = moment_timeZone.tz(`${todayStr} ${hh.padStart(2, '0')}:${mm.padStart(2, '0')}:00`, 'YYYY-MM-DD HH:mm:ss', 'Asia/Kolkata');
            return istMoment.toDate(); // JS Date object in IST
        };

        all_fix_values = {
            ...all_fix_values,
            withdraw_open_time: parseTimeToIST(all_fix_values.withdraw_open_time),
            withdraw_close_time: parseTimeToIST(all_fix_values.withdraw_close_time),
        };

        await fix_values_module.findOneAndUpdate({}, all_fix_values, { upsert: true });

        return res.json({ success: true, msg: "Values Successfully Updated." });
    } catch (error) {
        console.error("Error in addAdminFixValues:", error);
        res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};


const getFixValue = async (req, res) => {
    try {
        console.log("jjj", req.body);

        let all_fix_values = await fix_values_module.findOne().lean();

        if (!all_fix_values) {
            return res.status(404).json({ success: false, msg: "Fix values not found." });
        }

        let data = {};

        if (req?.body?.WL == true) {
            data = {
                withdrawLimit: all_fix_values?.withdrawLimit || 0,
                withdrawLimitChangeRemark: all_fix_values?.withdrawLimitChangeRemark || "",
            }
        } else {
            data = all_fix_values;
        }

        return res.json({ success: true, msg: "Values Successfully fetched.", data });

    } catch (error) {
        console.error("Error in addAdminFixValues:", error);
        res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};



const getContactSettings = async (req, res) => {
    try {
        let contact_data = await contact_settings_module.findOne().lean();
        return res.json({ success: true, msg: "Values Successfully fetched.", contact_data });
    } catch (error) {
        console.error("Error in addAdminFixValues:", error);
        res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};

const addContactSettings = async (req, res) => {
    const {
        mobile_1,
        telegram_username,
        whatsapp_no,
        otherUrl,
        landline_1,
        landline_2,
        email_1,
        email_2,
        facebook,
        twitter,
        youtube,
        google_plus,
        instagram,
        latitude,
        longitude,
        address
    } = req.body

    console.log(`(((((((()))))) ~ adminController.js:1207 ~ addContactSettings ~ req.body:`, req.body);

    try {
        await contact_settings_module.findOneAndUpdate({}, {
            $set: {
                mobile: mobile_1 || "",
                telegram_username: telegram_username || "",
                whatsapp_no: whatsapp_no || "",
                other: otherUrl || "",
                landline_1: landline_1 || "",
                landline_2: landline_2 || "",
                email_1: email_1 || "",
                email_2: email_2 || "",
                facebook: facebook || "",
                twitter: twitter || "",
                youtube: youtube || "",
                google_plus: google_plus || "",
                instagram: instagram || "",
                latitude: latitude || "",
                logitude: longitude || "",
                address: address || "",
            }
        }, { upsert: true })


        return res.status(200).json({ success: true, msg: "Contact Settings Updated Successfully" })
    } catch (error) {
        console.log("error in addContactSettings", error);
        return res.status(500).json({ success: false, msg: "Internal Server Error" })
    }


};


//slider image
// const sliderImagesListGridData = async (req, res) => {
//     try {
//         const baseUrl = process?.env?.BASE_URL;
//         if (!baseUrl) {
//             return res.status(500).json({ success: false, msg: "Base URL not set" });
//         }

//         const fields = ["image_title", "display_order", "insert_date", "status"];
//         const limit = parseInt(req?.body?.length) || 10;
//         const page = parseInt(req?.body?.start) || 1;

//         const searchValue = (req?.body?.searchValue || '').trim();
//         const fieldIndex = req?.body?.fieldIndex ?? 0;
//         const orderField = fields[fieldIndex] || "insert_date";
//         const orderDir = req?.body?.order ?? -1;

//         // Build search query
//         let searchQuery = {};
//         if (searchValue) {
//             const isNumeric = !isNaN(searchValue);
//             if (isNumeric) {
//                 searchQuery = {
//                     $or: [
//                         {
//                             $expr: {
//                                 $regexMatch: {
//                                     input: { $toString: "$display_order" },
//                                     regex: `^${searchValue}`,
//                                     options: "i",
//                                 },
//                             },
//                         },
//                     ],
//                 };
//             } else {
//                 searchQuery = {
//                     $or: [
//                         { image_title: { $regex: `^${searchValue}`, $options: "i" } },
//                     ],
//                 };
//             }
//         }

//         const skip = !searchValue ? (page - 1) * limit : 0;

//         // Total filtered records
//         const totalFiltered = await slider_images_module.countDocuments(searchQuery);

//         // Get paginated & sorted data
//         const rawDataList = await slider_images_module
//             .find(searchQuery)
//             .sort({ [orderField]: orderDir })
//             .skip(skip)
//             .limit(limit)
//             .populate("slider_image")
//             .lean();

//         // Format and map the results
//         const data = rawDataList.map((doc) => {
//             const imageUrl = doc.slider_image
//                 ? `${baseUrl}/file/uploads/images/${doc.slider_image._id}`
//                 : "N/A";

//             return {
//                 ...doc,
//                 slider_image: imageUrl,
//                 insert_date:
//                     formatDateToDDMMYYYY(doc.insert_date) +
//                     " , " +
//                     get12HoursTimeFromISO(doc.insert_date),
//             };
//         });

//         // Final response
//         return res.json({
//             success: true,
//             recordsFiltered: totalFiltered,
//             limit,
//             data,
//         });
//     } catch (err) {
//         console.error("Error in sliderImagesListGridData:", err);
//         return res.status(500).json({ success: false, error: "Server Error" });
//     }
// };

// const addSliderImage = async (req, res) => {
//     try {
//         const baseUrl = process?.env?.BASE_URL;
//         if (!baseUrl) {
//             return res.status(500).json({ success: false, msg: "Base URL not set" });
//         }

//         const { display_order = "" } = req.body || {};

//         // Validate display order
//         if (!display_order || isNaN(display_order)) {
//             return res.status(400).json({ success: false, msg: "Display order is required and must be a number." });
//         }

//         // Check if image file is provided
//         if (!req.file || !req.file.buffer || !req.file.mimetype) {
//             return res.status(400).json({ success: false, msg: "Valid image file is required." });
//         }

//         // Check for duplicate display order
//         const isDisplayOrderExist = await slider_images_module.findOne({ display_order });
//         if (isDisplayOrderExist) {
//             return res.status(409).json({ success: false, msg: `Display order "${display_order}" already exists.` });
//         }

//         // Save image in DB
//         const image = new file_module({
//             fileInfo: {
//                 fileBuffer: req.file.buffer,
//                 content_type: req.file.mimetype,
//             },
//         });
//         const savedImage = await image.save();

//         let sliderData = new slider_images_module({
//             slider_image: savedImage._id,
//             display_order: parseInt(display_order),
//         });

//         sliderData = await sliderData.save();
//         const leanSliderData = sliderData.toObject();

//         const imageUrl = leanSliderData.slider_image
//             ? `${baseUrl}/file/uploads/images/${leanSliderData.slider_image}`
//             : "N/A";


//         sliderData = {
//             ...leanSliderData,
//             slider_image: imageUrl,
//             insert_date:
//                 formatDateToDDMMYYYY(leanSliderData.insert_date) +
//                 " , " +
//                 get12HoursTimeFromISO(leanSliderData.insert_date),
//         }

//         res.status(200).json({
//             success: true,
//             msg: "Slider image successfully added.",
//             sliderData
//         });
//     } catch (err) {
//         console.error("Add Slider Image Error:", err);
//         res.status(500).json({
//             success: false,
//             msg: "Internal Server Error",
//         });
//     }
// };

// const deleteSliderImage = async (req, res) => {
//     try {
//         const { imageDB_id = "" } = req?.body || {};

//         if (!imageDB_id) {
//             return res.status(400).json({ success: false, msg: 'Missing required fields' });
//         }

//         if (!mongoose.isValidObjectId(imageDB_id)) {
//             return res.status(400).json({
//                 success: false,
//                 msg: "Invalid how_to_playDB_id.",
//             });
//         }

//         const image = await slider_images_module.findOne({ _id: imageDB_id });

//         if (!image) {
//             return res.json({
//                 success: false,
//                 msg: 'Image not found'
//             });
//         }

//         await file_module.findByIdAndDelete(image?.slider_image)

//         await slider_images_module.findByIdAndDelete(imageDB_id);

//         res.json({
//             success: true,
//             msg: 'Image Successfully Deleted'
//         });

//     } catch (err) {
//         res.status(500).json({
//             success: false,
//             msg: 'Internal Server Error'
//         });
//     }
// };


const addSliderImage = async (req, res) => {
    try {
        console.log(`(((((((()))))) ~ adminController.js:1607 ~ addSliderImage ~ req.file:`, req.file);
        if (!req.file) {
            return res.json({ success: false, msg: "No file uploaded" });
        }

        // Create new image document with file path instead of buffer
        const newImage = new slider_images_module({
            filename: req.file.filename, // The unique filename generated by multer
            originalName: req.file.originalname,
            filePath: req.file.path, // Store the file path on disk
            size: req.file.size,
            mimetype: req.file.mimetype,
            redirect_url: req.body.redirect_url || "",
            status: parseInt(req.body.status) || 1,
        });

        await newImage.save();

        res.json({
            success: true,
            msg: "Image uploaded successfully",
            data: {
                filename: req.file.filename,
                path: req.file.path
            }
        });
    } catch (error) {
        console.error("Error saving slider image:", error);
        res.json({ success: false, msg: error.message });
    }
};


// Get All Slider Images - Updated version
const getSliderImages = async (req, res) => {
    try {
        const images = await slider_images_module.find().sort({ createMkt: -1 });

        const transformedImages = images.map((img, index) => {
            return {
                _id: img._id,
                id: index + 1,
                filename: img.filename,
                filePath: img.filePath,
                redirect_url: img.redirect_url,
                status: img.status,
                createdAt: img.createMkt,
                updatedAt: img.updatedMkt,
                // Add URL for frontend access
                imageUrl: `/uploads/slider-images/${img.filename}`
            };
        });

        res.json({
            success: true,
            data: transformedImages
        });
    } catch (error) {
        console.error('Error fetching slider images', error);
        res.status(500).json({
            success: false,
            msg: 'Server error occurred while fetching slider images'
        });
    }
};




// Delete Slider Image
const deleteSliderImage = async (req, res) => {
    try {
        const { imageId } = req.body;

        // Find the image first
        const image = await slider_images_module.findById(imageId);
        if (!image) {
            return res.json({ success: false, msg: "Image not found" });
        }

        // Delete the physical file from disk
        if (fs.existsSync(image.filePath)) {
            fs.unlinkSync(image.filePath);
        }

        // Delete from database
        await slider_images_module.findByIdAndDelete(imageId);

        res.json({ success: true, msg: "Image deleted successfully" });
    } catch (error) {
        console.error("Error deleting slider image:", error);
        res.json({ success: false, msg: error.message });
    }
};







const getHowToPlayData = async (req, res) => {
    try {
        const how_to_play_content = await how_to_play_module.findOne().lean();

        return res.status(200).json({
            success: true,
            msg: "Content fetched successfully",
            htmlContent: how_to_play_content,
        });

    } catch (err) {
        console.error("âŒ getHowToPlayData Error:", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
};

const addHowToPlayData = async (req, res) => {
    try {
        let { how_to_play_content = '', video_link = '' } = req?.body?.content_state || {};

        console.log(req?.body?.content_state)

        how_to_play_content = toStr(how_to_play_content)
        video_link = toStr(video_link)

        if (!how_to_play_content || !video_link) {
            return res.status(400).json({ success: false, msg: 'Missing required fields' });
        }

        const playData = {
            how_to_play_content,
            video_link: video_link,
        };

        await how_to_play_module.findOneAndUpdate({}, playData, { upsert: true });
        res.json({
            success: true,
            msg: 'Play Content Successfully Added.'
        });

    } catch (err) {
        console.error(err);
        res.status(500).json({
            success: false,
            msg: 'Something went wrong.'
        });
    }
}

const subAdminListGridData = async (req, res) => {
    try {
        let fields = [
            "full_name",  // "Full Name",
            "username",  // "User Name",
            "admin_email",  // "Admin Email",
            "insert_date",  // "Creation Date",
            "status",  // "Status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;

        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = req?.body?.order || -1

        let searchQuery = { admin_type: 1 };

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                searchQuery = {
                    admin_type: 1,
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            }
                        }
                    ]
                };
            } else {
                searchQuery = {
                    admin_type: 1,
                    $or: [
                        { full_name: { $regex: regexValue, $options: 'i' } },
                        { username: { $regex: regexValue, $options: 'i' } },
                        { admin_email: { $regex: regexValue, $options: 'i' } },
                    ]
                };
            }
        }

        const totalFiltered = await admin_module.countDocuments(searchQuery);

        const results = await admin_module.find(searchQuery)
            .sort({ [orderField]: orderDir })
            .skip(skip)
            .limit(limit)
            .lean();

        const data = results.map((rs) => ({
            _id: rs._id,
            full_name: rs.full_name,
            user_name: rs.username,
            email: rs.admin_email,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
            status: rs.status,
            accessMenus: rs.accessMenus,
            phone: rs.phone,
            role: rs.role || '',
            commission: rs.commission || ''
        }));

        res.json({
            recordsFiltered: totalFiltered,
            data,
            limit,
        });

    } catch (error) {
        console.error("Error in subAdminListGridData:", error);
        res.status(500).json({
            success: false,
            msg: 'Something went wrong.',
        });
    }
};

const addSubAdmin = async (req, res) => {
    try {
        let {
            name = '',
            email = '',
            username = '',
            password = '',
            status = 0,
            accessMenus = [],
            phone_number = '',
            role,
            commission
        } = req.body || {};

        console.log(`(((((((()))))) ~ adminController.js:1584 ~ addSubAdmin ~ req.body:`, req.body);

        const full_name = toStr(name).trim();
        email = toStr(email).trim();
        username = toStr(username).trim();
        password = toStr(password).trim();
        status = Number(status);
        phone_number = toStr(phone_number).trim();

        // Basic validations
        if (!full_name || !email || !username || !password || !phone_number) {
            return res.status(400).json({ success: false, msg: 'All fields are required.' });
        }

        const mobileRegex = /^\d{10}$/;
        if (!mobileRegex.test(phone_number)) {
            return res.status(400).json({ success: false, msg: 'Invalid mobile number. Must be exactly 10 digits.' });
        }

        if (!Array.isArray(accessMenus) || accessMenus.length === 0) {
            return res.status(400).json({ success: false, msg: 'At least one access menu must be selected.' });
        }

        // âœ… Check for duplicate username/email/phone
        const existingAdmin = await admin_module.findOne({
            $or: [
                { username },
                { admin_email: email },
                { phone: Number(phone_number) }
            ]
        });

        if (existingAdmin) {
            let conflictField = '';
            if (existingAdmin.username === username) conflictField = 'Username';
            else if (existingAdmin.admin_email === email) conflictField = 'Email';
            else if (existingAdmin.phone === Number(phone_number)) conflictField = 'Phone Number';

            return res.status(409).json({
                success: false,
                msg: `${conflictField} is already registered.`
            });
        }

        // Encrypt password
        const encryptedPassword = await bcrypt.hash(password, 10);

        const userdata = {
            full_name: capitalizeWords(full_name),
            admin_email: email,
            username,
            password: encryptedPassword,
            // admin_type: 1,
            accessMenus,
            status,
            phone: Number(phone_number)
        };

        if (role) {
            userdata.role = role;


            if (role === 'agent') userdata.commission = commission
        }
        console.log(`(((((((()))))) ~ adminController.js:1646 ~ addSubAdmin ~ userdata:`, userdata);

        let added_sub_admin = await admin_module.create(userdata);

        return res.json({
            success: true,
            msg: 'Sub Admin successfully added.',
            insert_date: `${formatDateToDDMMYYYY(added_sub_admin.insert_date)} , ${get12HoursTimeFromISO(added_sub_admin.insert_date)}`,
            _id: added_sub_admin._id
        });

    } catch (error) {
        console.error('Error in addSubAdmin:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const updateSubAdmin = async (req, res) => {
    try {
        let {
            name = '',
            email = '',
            username = '',
            status = 0,
            accessMenus = [],
            phone_number = ''
        } = req.body || {};

        let adminDB_id = req.params.adminDB_id

        const full_name = toStr(name).trim();
        email = toStr(email).trim();
        username = toStr(username).trim();
        status = Number(status);
        phone_number = toStr(phone_number).trim();

        // Basic validations
        if (!full_name || !email || !username || !adminDB_id || !phone_number) {
            return res.status(400).json({ success: false, msg: 'All fields are required.' });
        }

        if (!mongoose.isValidObjectId(adminDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid admin ID. Please provide a valid ObjectId.'
            });
        }

        const mobileRegex = /^\d{10}$/;
        if (!mobileRegex.test(phone_number)) {
            return res.status(400).json({ success: false, msg: 'Invalid mobile number. Must be exactly 10 digits.' });
        }

        if (!Array.isArray(accessMenus) || accessMenus.length === 0) {
            return res.status(400).json({ success: false, msg: 'At least one access menu must be selected.' });
        }

        await admin_module.findOneAndUpdate({ _id: adminDB_id }, { full_name, email, username, phone: phone_number, status, accessMenus });

        return res.json({
            success: true,
            msg: 'Sub Admin successfully updated.',
        });
    } catch (error) {
        console.error('Error in addSubAdmin:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const deleteSubAdmin = async (req, res) => {
    try {
        let {
            adminDB_id = ''
        } = req.body || {};

        adminDB_id = toStr(adminDB_id).trim();

        // Basic validations
        if (!adminDB_id) {
            return res.status(400).json({ success: false, msg: 'adminDB_id are required.' });
        }

        if (!mongoose.isValidObjectId(adminDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid admin ID. Please provide a valid ObjectId.'
            });
        }

        await admin_module.findByIdAndDelete(adminDB_id);

        return res.json({
            success: true,
            msg: 'Sub Admin successfully Deleted.',
        });
    } catch (error) {
        console.error('Error in addSubAdmin:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const noticeListGridData = async (req, res) => {
    try {
        let fields = [
            "notice_title",  // "Notice Title English",
            "notice_msg",  // "Content English",
            "last_update",  // "Last Update",
            "insert_date",  // "Create At",
            "status",  // "Status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = req?.body?.order || -1

        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            }
                        }
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { notice_title: { $regex: regexValue, $options: 'i' } },
                        { notice_msg: { $regex: regexValue, $options: 'i' } },
                    ]
                };
            }
        }

        const totalFiltered = await notice_module.countDocuments(searchQuery);

        const results = await notice_module.find(searchQuery)
            .sort({ [orderField]: orderDir })
            .skip(skip)
            .limit(limit)
            .lean();

        const data = results.map((rs) => ({
            _id: rs._id,
            notice_title: rs.notice_title,
            notice_msg: rs.notice_msg,
            last_update: `${formatDateToDDMMYYYY(rs.last_update)} , ${get12HoursTimeFromISO(rs.last_update)}`,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
            status: rs.status,
        }));

        res.json({
            recordsFiltered: totalFiltered,
            data,
            limit,
        });
    } catch (err) {
        console.error('Error fetching notice list:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal server error'
        });
    }
};

const addNotice = async (req, res) => {
    try {
        let {
            notice_title = '',
            notice_msg = ''
        } = req.body || {};

        // Convert to string and trim
        notice_title = toStr(notice_title);
        notice_msg = toStr(notice_msg);
        // status = Number(status);
        // create_at = toStr(create_at);

        // Basic validation 
        // (status !== 0 && !(status > 0)) ||  !create_at
        if (
            !notice_title ||
            !notice_msg

        ) {
            return res.status(400).json({
                success: false,
                msg: 'All fields are required.'
            });
        }

        // Convert create_at string to IST Date object using moment_timeZone-timezone
        // const insertDateIST = moment_timeZone.tz(create_at, 'Asia/Kolkata').toDate();

        let noticeData = {
            notice_title: notice_title.replace(/\b\w/g, c => c.toUpperCase()),
            notice_msg,
            // status,
            // insert_date: insertDateIST,
            // last_update: getISTDateObject()
        };

        noticeData = await notice_module.create(noticeData);

        return res.json({
            success: true,
            msg: 'Notice successfully added.',
            _id: noticeData._id,
            last_update: `${formatDateToDDMMYYYY(noticeData.last_update)} , ${get12HoursTimeFromISO(noticeData.last_update)}`,
            insert_date: `${formatDateToDDMMYYYY(noticeData.insert_date)} , ${get12HoursTimeFromISO(noticeData.insert_date)}`,
        });

    } catch (error) {
        console.error('Error in addNotice:', error);
        return res.status(500).json({
            success: false,
            msg: 'Internal server error.'
        });
    }
};

const updateNotice = async (req, res) => {
    try {
        let {
            notice_title = '',
            notice_msg = '',
            status = '',
            create_at = ''
        } = req.body || {};

        let noticeDB_id = req.params.noticeDB_id

        // Convert to string and trim
        notice_title = toStr(notice_title);
        notice_msg = toStr(notice_msg);
        noticeDB_id = toStr(noticeDB_id);
        status = Number(status);
        create_at = toStr(create_at);

        // Basic validation
        if (
            !notice_title ||
            !notice_msg ||
            status !== 0 && !(status > 0) ||
            !noticeDB_id ||
            !create_at
        ) {
            return res.status(400).json({
                success: false,
                msg: 'All fields are required.'
            });
        }

        if (!mongoose.isValidObjectId(noticeDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid notice ID. Please provide a valid ObjectId.'
            });
        }

        let noticeData = {
            notice_title: notice_title.replace(/\b\w/g, c => c.toUpperCase()),
            notice_msg,
            status,
            last_update: new Date(create_at)
        };


        noticeData = await notice_module.findByIdAndUpdate(noticeDB_id, noticeData, { new: true });

        return res.json({
            success: true,
            msg: 'Notice successfully added.',
            _id: noticeData._id,
            last_update: `${formatDateToDDMMYYYY(noticeData.last_update)} , ${get12HoursTimeFromISO(noticeData.last_update)}`,
        });

    } catch (error) {
        console.error('Error in addNotice:', error);
        return res.status(500).json({
            success: false,
            msg: 'Internal server error.'
        });
    }
};

const deleteNotice = async (req, res) => {
    try {
        let {
            noticeDB_id
        } = req?.body || {};

        noticeDB_id = toStr(noticeDB_id);

        if (!noticeDB_id) {
            return res.status(400).json({
                success: false,
                msg: 'noticeDB_id field is Required'
            });
        }

        if (noticeDB_id && !mongoose.isValidObjectId(noticeDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid notice ID'
            });
        }

        await notice_module.findByIdAndDelete(noticeDB_id);
        let responseData = {}
        responseData.success = true;
        responseData.msg = 'Notice successfully deleted.';

        return res.json(responseData);

    } catch (error) {
        console.error('Error adding/add notice:', error);
        return res.status(500).json({ success: false, msg: 'Internal server error' });
    }
};

const getSendNotification_users_date = async (req, res) => {
    try {
        let allUsers = await user_module.find({}, 'user_name mobile _id')
        let responseData = {}
        responseData.success = true;
        responseData.data = allUsers;
        return res.json(responseData);
    } catch (error) {
        console.error('Error get notification', error);
        return res.status(500).json({ success: false, msg: 'Internal server error' });
    }
};

const sendNotification = async (req, res) => {
    try {
        let { user, title_en, content_en } = req.body || {};

        title_en = toStr(title_en).trim();
        content_en = toStr(content_en).trim();

        if (!title_en || !content_en) {
            return res.status(400).json({ success: false, msg: "Title and content are required." });
        }

        if (user === "all") {
            const notice = await notice_module.create({
                notice_title: title_en,
                notice_msg: content_en,
            });

            if (!notice) {
                return res.status(500).json({ success: false, msg: "Failed to send global notice." });
            }

            return res.json({ success: true, msg: "Notice sent to all users successfully." });
        }

        if (!user || typeof user !== "string") {
            return res.status(400).json({ success: false, msg: "Invalid user input." });
        }

        const match = user.match(/\((\d{10,})\)/);
        if (!match || !match[1]) {
            return res.status(400).json({ success: false, msg: "Mobile number not found in user input." });
        }

        const mobile = match[1];
        const userDoc = await user_module.findOne({ mobile }).select('_id').lean();

        if (!userDoc?._id) {
            return res.status(404).json({ success: false, msg: "User not found." });
        }

        const inserted = await user_notification_module.create({
            userDB_id: userDoc._id,
            title: title_en,
            msg: content_en,
        });

        if (!inserted) {
            return res.status(500).json({ success: false, msg: "Failed to send notification to user." });
        }

        return res.json({ success: true, msg: "Notification sent successfully to selected user." });

    } catch (error) {
        console.error("Error in sendNotification:", error);
        return res.status(500).json({ success: false, msg: "Internal server error." });
    }
};

const gameNameListGridData = async (req, res) => {
    try {
        let fields = [
            "game_name",  // "Game Name",
            "open_time",  // "Today Open",
            "close_time",  // "Today Close",
            "status",  // "Active",
            "market_status",  // "Market Status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "game_name";
        const orderDir = req?.body?.order || -1

        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            },
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$market_status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            },
                        }
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { game_name: { $regex: regexValue, $options: 'i' } },
                    ]
                };
            }
        }

        const todayName = getWeekdayNameInIST()

        const aggregatePipeline = [
            {
                $lookup: {
                    from: 'weekday_games',
                    localField: '_id',
                    foreignField: 'gameDB_id',
                    as: 'weekdayData'
                }
            },
            {
                $addFields: {
                    weekdayData: {
                        $first: {
                            $filter: {
                                input: '$weekdayData',
                                as: 'item',
                                cond: { $eq: ['$$item.week_name', todayName?.toLocaleLowerCase()] }
                            }
                        }
                    }
                }
            },
            {
                $match: searchQuery
            },
            {
                $sort: { [orderField]: orderDir }
            },
            {
                $facet: {
                    data: [
                        { $skip: skip },
                        { $limit: limit }
                    ],
                    totalCount: [
                        { $count: 'count' }
                    ]
                }
            }
        ];

        const result = await games_module.aggregate(aggregatePipeline);

        const tb_data = result[0].data || [];
        const totalData = result[0].totalCount[0]?.count || 0;


        const data = tb_data.map((rs) => {
            return {
                _id: rs._id,
                game_name: rs.game_name?.toUpperCase() || '',
                open_time: get12HoursTimeFromISO(rs?.weekdayData?.open_time) || '',
                close_time: get12HoursTimeFromISO(rs?.weekdayData?.close_time) || '',
                status: rs.status,
                gameDB_id: rs._id,
                market_status: rs.weekdayData?.weekday_status || 0,
            };
        });

        const json_data = {
            success: true,
            recordsFiltered: totalData,
            data,
            limit
        };
        res.json(json_data);
    } catch (err) {
        console.error('Error in gameNameListGridData:', err);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const gameNameListGridDataUpdate = async (req, res) => {
    try {
        const { gameDB_id } = req.params;

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid game ID.',
            });
        }

        const weekdayGames = await weekday_games_module.find({ gameDB_id }).lean();

        // Format date fields using moment_timeZone
        const formattedResults = weekdayGames.map((game) => ({
            ...game,
            open_time: game.open_time && moment_timeZone(game.open_time).isValid()
                ? moment_timeZone(game.open_time).tz('Asia/Kolkata').format('HH:mm')
                : 'N/A',
            close_time: game.close_time && moment_timeZone(game.close_time).isValid()
                ? moment_timeZone(game.close_time).tz('Asia/Kolkata').format('HH:mm')
                : 'N/A',
        }));

        // Response
        return res.json({
            success: true,
            results: formattedResults || [],
        });

    } catch (err) {
        console.error('Error fetching weekday games:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal Server Error',
        });
    }
};

const addOffDay = async (req, res) => {
    try {
        const { gameDB_id } = req.body;

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid game ID.',
            });
        }

        const existingWeekdays = await weekday_games_module.find({ gameDB_id }).populate('gameDB_id');

        if (!existingWeekdays.length) {
            return res.status(404).json({
                success: false,
                msg: 'No weekday records found for this game.',
            });
        }

        let marketStatus = 1;

        for (let i = 0; i < 7; i++) {
            const dayData = req.body[i];
            if (dayData && typeof dayData === 'object') {
                const { name, status, open_time, close_time } = dayData;

                if (moment_timeZone().tz('Asia/Kolkata').format('dddd').toLowerCase() === name?.toLowerCase() && status === 0) {
                    marketStatus = 0;
                }

                if (!name) continue;

                const updateData = {
                    weekday_status: Number(status),
                };

                if (open_time) {
                    const [hours, minutes] = open_time.split(':').map(Number);
                    const openDate = moment_timeZone().tz('Asia/Kolkata').startOf('day')
                        .set({ hour: hours, minute: minutes })
                        .toDate(); // Convert to UTC Date object
                    updateData.open_time = openDate;
                }

                if (close_time) {
                    const [hours, minutes] = close_time.split(':').map(Number);
                    const closeDate = moment_timeZone().tz('Asia/Kolkata').startOf('day')
                        .set({ hour: hours, minute: minutes })
                        .toDate(); // Convert to UTC Date object
                    updateData.close_time = closeDate;
                }

                if (existingWeekdays?.gameDB_id) {
                    updateData.name = existingWeekdays?.gameDB_id?.game_name;
                }

                await weekday_games_module.findOneAndUpdate(
                    { gameDB_id, week_name: name?.toLowerCase() },
                    { $set: updateData },
                    { upsert: true }
                );
            }
        }

        return res.json({
            success: true,
            msg: 'Market Off Day Updated Successfully.',
            marketStatus,
            gameDB_id,
        });

    } catch (err) {
        console.error('Error in addOffDay:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal Server Error',
        });
    }
};

const addUpdateGame = async (req, res) => {
    try {
        let {
            game_name = "",
            open_time = "",  // Expected format: "HH:mm"
            close_time = "",
            gameDB_id
        } = req.body || {};

        game_name = toStr(game_name).trim();
        open_time = toStr(open_time).trim();
        close_time = toStr(close_time).trim();
        gameDB_id = toStr(gameDB_id).trim();

        if (!game_name || !open_time || !close_time) {
            return res.status(400).json({ success: false, msg: "All fields are required." });
        }

        if (gameDB_id && !mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        // Convert time to IST timezone using a dummy date
        const todayStr = moment_timeZone().tz('Asia/Kolkata').format('YYYY-MM-DD');

        const openTimeIST = moment_timeZone.tz(`${todayStr} ${open_time}`, 'YYYY-MM-DD HH:mm', 'Asia/Kolkata').toDate();
        const closeTimeIST = moment_timeZone.tz(`${todayStr} ${close_time}`, 'YYYY-MM-DD HH:mm', 'Asia/Kolkata').toDate();

        const gameData = {
            game_name: game_name.toUpperCase(),
            open_time_sort: openTimeIST,
            status: 1,
        };

        const weekDays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

        if (!gameDB_id) {
            const newGame = await games_module.create(gameData);
            const weekEntries = weekDays.map((day) => ({
                gameDB_id: newGame._id,
                name: game_name.toUpperCase(),
                week_name: day.toLowerCase(),
                open_time: openTimeIST,
                open_time_sort: openTimeIST,
                close_time: closeTimeIST,
                weekday_status: 1
            }));
            await weekday_games_module.insertMany(weekEntries);

            return res.status(200).json({
                success: true,
                msg: "Game added successfully.",
                _id: newGame._id,
                open_time: moment_timeZone(openTimeIST).format('hh:mm A'),
                close_time: moment_timeZone(closeTimeIST).format('hh:mm A')
            });
        } else {
            for (let i = 0; i < weekDays.length; i++) {
                if (getWeekdayNameInIST()?.toUpperCase() === weekDays[i]?.toUpperCase()) {
                    await weekday_games_module.updateOne(
                        { gameDB_id, week_name: weekDays[i].toLowerCase() },
                        {
                            $set: {
                                name: game_name.toUpperCase(),
                                open_time: openTimeIST,
                                open_time_sort: openTimeIST,
                                close_time: closeTimeIST,
                            }
                        }
                    );
                } else {
                    await weekday_games_module.updateOne(
                        { gameDB_id, week_name: weekDays[i].toLowerCase() },
                        { $set: { name: game_name.toUpperCase() } }
                    );
                }
            }

            await games_module.updateOne({ _id: gameDB_id }, gameData);

            return res.status(200).json({
                success: true,
                msg: "Game updated successfully.",
                _id: gameDB_id,
                open_time: moment_timeZone(openTimeIST).format('hh:mm A'),
                close_time: moment_timeZone(closeTimeIST).format('hh:mm A')
            });
        }

    } catch (err) {
        console.error("Error in addUpdateGame:", err);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong."
        });
    }
};

const deleteGameName = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const gameDB_id = toStr(req?.body?.gameDB_id || '');

        if (!gameDB_id) {
            return res.status(400).json({ success: false, msg: "gameDB_id is required." });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const istNow = moment_timeZone().tz('Asia/Kolkata');
        const startDate = istNow.clone().startOf('day').toDate();
        const endDate = istNow.clone().endOf('day').toDate();

        const allBids = await bid_history_module.find({ gameDB_id }).session(session);

        const [isOpenDeclared, isCloseDeclared] = await Promise.all([
            game_result_history_module.findOne({
                gameDB_id,
                result_date: { $gte: startDate, $lte: endDate },
                open_decleare_status: 1
            }).session(session),
            game_result_history_module.findOne({
                gameDB_id,
                result_date: { $gte: startDate, $lte: endDate },
                close_decleare_status: 1
            }).session(session)
        ]);

        for (const bid of allBids) {
            const isOpenSession = bid.session === 'Open';
            const isCloseSession = bid.session === 'Close';

            if ((isOpenSession && isOpenDeclared) || (isCloseSession && isCloseDeclared)) {
                continue;
            }

            const user = await user_module.findById(bid.userDB_id).session(session);
            if (!user) continue;

            user.wallet_balance += bid.points;
            await user.save({ session });

            const historyData = {
                userDB_id: user._id,
                amount: bid.points,
                transaction_type: 1,
                transaction_note: `Refund issued for deleted game "${bid.game_name}" (${bid.session} session)`,
                amount_status: 7,
                tx_request_number: getUserRandomToken(10),
            };

            bid.pay_status = 3;

            await Promise.all([
                wallet_trans_history_module.create([historyData], { session }),
                bid.save({ session })
            ]);
        }

        await Promise.all([
            games_module.findByIdAndDelete(gameDB_id, { session }),
            game_result_history_module.deleteMany({ gameDB_id }, { session }),
            weekday_games_module.deleteMany({ gameDB_id }, { session })
        ]);

        await session.commitTransaction();
        session.endSession();

        return res.json({
            success: true,
            msg: "Game deleted and eligible bids refunded successfully."
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.error('Error deleting game:', error);

        return res.status(500).json({
            success: false,
            msg: "An error occurred while deleting the game.",
            error: error.message
        });
    }
};

const getGameRates = async (req, res) => {
    try {
        let gameRates = await game_rates_module.findOne()

        return res.json({
            success: true,
            msg: "Game Rates successfull sended.",
            game_rates: gameRates
        });
    } catch (error) {
        console.error("Error in addGameRates:", error);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
};

const addGameRates = async (req, res) => {
    try {
        const {
            single_digit_val_1,
            single_digit_val_2,
            jodi_digit_val_1,
            jodi_digit_val_2,
            single_pana_val_1,
            single_pana_val_2,
            double_pana_val_1,
            double_pana_val_2,
            tripple_pana_val_1,
            tripple_pana_val_2,
            half_sangam_val_1,
            half_sangam_val_2,
            full_sangam_val_1,
            full_sangam_val_2,
            red_bracket_val_1,
            red_bracket_val_2,
            group_jodi_val_1,
            group_jodi_val_2,
        } = req.body;

        const fields = [
            single_digit_val_1,
            single_digit_val_2,
            jodi_digit_val_1,
            jodi_digit_val_2,
            single_pana_val_1,
            single_pana_val_2,
            double_pana_val_1,
            double_pana_val_2,
            tripple_pana_val_1,
            tripple_pana_val_2,
            half_sangam_val_1,
            half_sangam_val_2,
            full_sangam_val_1,
            full_sangam_val_2,
            red_bracket_val_1,
            red_bracket_val_2,
            group_jodi_val_1,
            group_jodi_val_2
        ];

        const hasAtLeastOneValue = fields.some(value => value !== undefined && value !== null && value !== '');

        if (!hasAtLeastOneValue) {
            return res.status(400).json({ success: false, msg: "At least one field is required." });
        }

        const gamesRatesData = {
            single_digit_val_1,
            single_digit_val_2,
            jodi_digit_val_1,
            jodi_digit_val_2,
            single_pana_val_1,
            single_pana_val_2,
            double_pana_val_1,
            double_pana_val_2,
            tripple_pana_val_1,
            tripple_pana_val_2,
            half_sangam_val_1,
            half_sangam_val_2,
            full_sangam_val_1,
            full_sangam_val_2,
            red_bracket_val_1,
            red_bracket_val_2,
            group_jodi_val_1,
            group_jodi_val_2
        };

        let gameRates = await game_rates_module.findOne()

        if (!gameRates) {
            await game_rates_module.create(gamesRatesData);
            return res.json({
                success: true,
                msg: "Game Rates Successfully Added.",
            });
        } else {
            await game_rates_module.updateOne({}, gamesRatesData);
            return res.json({
                success: true,
                msg: "Game Rates Successfully Updated.",
            });
        }
    } catch (error) {
        console.error("Error in addGameRates:", error);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
};

const userListGridData = async (req, res) => {
    try {
        let fields = [
            "user_name",  // "User Name",
            "mobile",  // "mobile",
            "email",  // "Email",
            "wallet_balance",  // "balance",
            "last_update",  // "Date",
            "is_agent",  // "is agent",
            "betting_status",  // "betting",
            "transfer_point_status",  // "transfer",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;

        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "last_update";
        const orderDir = req?.body?.order || -1

        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                // console.log("searc numeric", regexValue)
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$mobile" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$wallet_balance" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            }
                        },
                    ]
                };
            } else {
                // console.log("searc string", regexValue)

                searchQuery = {
                    user_name: { $regex: regexValue }
                };
            }
            // console.log("searchquery", searchQuery)
        }

        const totalFiltered = await user_module.countDocuments(searchQuery);

        const results = await user_module.find(searchQuery)
            .sort({ [orderField]: orderDir })
            .skip(skip)
            .limit(limit)
            .lean();

        // console.log("result-", results)

        const data = results.map((rs) => ({
            _id: rs._id,
            user_name: rs.user_name,
            email: rs.email,
            last_update: `${formatDateToDDMMYYYY(rs.last_update)} , ${get12HoursTimeFromISO(rs.last_update)}`,
            wallet_balance: rs.wallet_balance,
            status: rs.status,
            is_agent: rs.is_agent,
            betting_status: rs.betting_status,
            transfer_point_status: rs.transfer_point_status,
            mobile: rs.mobile
        }));

        const json_data = {
            recordsFiltered: totalFiltered,
            data,
            limit
        };
        // console.log("json_data-", json_data)

        res.json(json_data);
    } catch (error) {
        console.error(error);
        res.status(500).send('Error occurred while fetching user data');
    }
};

const userUpdateWallet = async (req, res) => {
    try {
        const { userDB_id, new_balance } = req.body;

        if (!userDB_id || new_balance === undefined) {
            return res.status(400).json({
                success: false,
                msg: "User ID and new balance are required",
            });
        }

        const updatedUser = await user_module.findByIdAndUpdate(
            userDB_id,
            { wallet_balance: Number(new_balance) },
            { new: true }
        );

        if (!updatedUser) {
            return res.status(404).json({
                success: false,
                msg: "User not found",
            });
        }

        res.json({
            success: true,
            msg: "Balance updated successfully",
            data: {
                _id: updatedUser._id,
                wallet_balance: updatedUser.wallet_balance,
            },
        });
    } catch (error) {
        console.error("Error updating wallet:", error);
        res.status(500).json({
            success: false,
            msg: "Error occurred while updating wallet balance",
        });
    }
};

const addBalanceUserWallet = async (req, res) => {
    try {
        let { userDB_id = "", amount = "" } = req?.body || {};
        userDB_id = toStr(userDB_id);
        amount = parseFloat(amount);

        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'userDB_id is required' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid userDB_id' });
        }

        if (isNaN(amount) || amount <= 0) {
            return res.status(400).json({ success: false, msg: 'Invalid amount' });
        }

        const user = await user_module.findOne({ _id: userDB_id });
        const before_Wallet_amount = user?.wallet_balance || 0;
        console.log("before_Wallet_amount", before_Wallet_amount)

        if (!user) {
            return res.status(404).json({ success: false, msg: 'User not found' });
        }

        await user_module.updateOne({ _id: userDB_id }, { $inc: { wallet_balance: amount } });

        const request_number = getUserRandomToken();

        await wallet_trans_history_module.create({
            userDB_id,
            amount,
            transaction_type: 1,
            transaction_note: 'Amount Added By Admin',
            amount_status: 1,
            before_wallet: before_Wallet_amount,
            tx_request_number: request_number,
        });

        const tx1 = await wallet_trans_history_module.find({ userDB_id, amount_status: 19 });
        const tx2 = await wallet_trans_history_module.find({ userDB_id, amount_status: 1 });

        if ((tx1.length + tx2.length) < 1) {
            const refer = await refer_details_module.findOne({ refer_to: userDB_id });

            if (refer) {
                const referByUser = await user_module.findOne({ _id: refer.refer_by });

                if (referByUser) {
                    const setting = await fix_values_module.findOne();

                    let bonus = 0;
                    if (referByUser.is_agent === 1) {
                        bonus = (amount * setting.agent_refer_bonus) / 100;
                    } else {
                        bonus = (amount * setting.user_refer_bonus) / 100;
                    }

                    await user_module.updateOne({ _id: referByUser._id }, { $inc: { wallet_balance: bonus } });

                    await refer_details_module.updateOne(
                        { refer_to: userDB_id, refer_by: refer.refer_by },
                        { $set: { bonus } }
                    );

                    const r_number = getUserRandomToken();

                    await wallet_trans_history_module.create({
                        userDB_id: referByUser._id,
                        amount: bonus,
                        transaction_type: 1,
                        transaction_note: 'User Refer Bonus',
                        amount_status: 6,
                        tx_request_number: r_number,
                    });
                }
            }
        }
        return res.json({ success: true, msg: 'Amount successfully added' });
    } catch (err) {
        console.error('Error in addBalanceUserWallet:', err);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getGameList = async (req, res) => {
    try {
        const gamesName = await games_module.find({}, 'game_name');
        return res.json({ success: true, gamesName });
    } catch (err) {
        console.error('Error in getGameList:', err);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getBidRevertData = async (req, res) => {
    try {
        const fields = [
            "user_name",    // 0
            "points",       // 1
            "bid_date",     // 2
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "bid_date";
        const orderDir = req?.body?.order || -1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const gameDB_id = req?.body?.gameDB_id?.trim();
        const bid_revert_date = req?.body?.date?.trim();

        if (!gameDB_id || !bid_revert_date) {
            return res.status(400).json({ success: false, msg: 'Missing required fields.' });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid gameDB_id.' });
        }

        const bidDateStart = moment_timeZone.tz(bid_revert_date, "Asia/Kolkata").startOf('day').toDate();
        const bidDateEnd = moment_timeZone.tz(bid_revert_date, "Asia/Kolkata").endOf('day').toDate();

        // Build aggregation
        const aggregationPipeline = [
            {
                $match: {
                    bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                }
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            {
                $unwind: {
                    path: '$user',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $addFields: {
                    user_name: "$user.user_name"
                }
            }
        ];

        // Add search filter
        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = new RegExp(`^${searchValue}`, 'i');

            aggregationPipeline.push({
                $match: {
                    $or: isNumeric
                        ? [
                            {
                                $expr: {
                                    $regexMatch: {
                                        input: { $toString: "$points" },
                                        regex: regexValue,
                                        options: 'i'
                                    }
                                }
                            }
                        ]
                        : [
                            {
                                user_name: { $regex: regexValue }
                            }
                        ]
                }
            });
        }

        aggregationPipeline.push(
            {
                $project: {
                    points: 1,
                    userDB_id: 1,
                    bid_date: 1,
                    user_name: 1
                }
            },
            {
                $sort: { [orderField]: orderDir }
            },
            {
                $facet: {
                    data: [
                        { $skip: skip },
                        { $limit: limit }
                    ],
                    totalCount: [
                        { $count: "count" }
                    ]
                }
            }
        );

        let result = await bid_history_module.aggregate(aggregationPipeline);

        const totalFiltered = result[0]?.totalCount[0]?.count || 0;
        results = result[0]?.data || [];

        results = results?.map(item => ({
            ...item,
            bid_date: formatDateToDDMMYYYY(item.bid_date)
        }));

        res.json({
            recordsFiltered: totalFiltered,
            data: results,
            limit
        });

    } catch (err) {
        console.error("getBidRevertData error:", err);
        res.status(500).json({
            success: false,
            msg: 'Something went wrong.'
        });
    }
};

const getStarlineBidRevertData = async (req, res) => {
    try {
        const fields = [
            "user_name",    // 0
            "points",       // 1
            "bid_date",     // 2
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "bid_date";
        const orderDir = req?.body?.order || -1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const gameDB_id = req?.body?.gameDB_id?.trim();
        const bid_revert_date = req?.body?.date?.trim();

        if (!gameDB_id || !bid_revert_date) {
            return res.status(400).json({ success: false, msg: 'Missing required fields.' });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid gameDB_id.' });
        }

        const bidDateStart = moment_timeZone.tz(bid_revert_date, "Asia/Kolkata").startOf('day').toDate();
        const bidDateEnd = moment_timeZone.tz(bid_revert_date, "Asia/Kolkata").endOf('day').toDate();

        // Build aggregation
        const aggregationPipeline = [
            {
                $match: {
                    bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                }
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            {
                $unwind: {
                    path: '$user',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $addFields: {
                    user_name: "$user.user_name"
                }
            }
        ];

        // Add search filter
        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = new RegExp(`^${searchValue}`, 'i');

            aggregationPipeline.push({
                $match: {
                    $or: isNumeric
                        ? [
                            {
                                $expr: {
                                    $regexMatch: {
                                        input: { $toString: "$points" },
                                        regex: regexValue,
                                        options: 'i'
                                    }
                                }
                            }
                        ]
                        : [
                            {
                                user_name: { $regex: regexValue }
                            }
                        ]
                }
            });
        }

        aggregationPipeline.push(
            {
                $project: {
                    points: 1,
                    userDB_id: 1,
                    bid_date: 1,
                    user_name: 1
                }
            },
            {
                $sort: { [orderField]: orderDir }
            },
            {
                $facet: {
                    data: [
                        { $skip: skip },
                        { $limit: limit }
                    ],
                    totalCount: [
                        { $count: "count" }
                    ]
                }
            }
        );

        const result = await starline_bid_history_module.aggregate(aggregationPipeline);

        const totalFiltered = result[0]?.totalCount[0]?.count || 0;
        let results = result[0]?.data || [];

        results = results?.map(item => ({
            ...item,
            bid_date: formatDateToDDMMYYYY(item.bid_date)
        }));

        res.json({
            recordsFiltered: totalFiltered,
            data: results,
            limit
        });

    } catch (err) {
        console.error("getStarlineBidRevertData error:", err);
        res.status(500).json({
            success: false,
            msg: 'Something went wrong.'
        });
    }
};

const getgalidisswarBidRevertData = async (req, res) => {
    try {
        const fields = [
            "user_name",    // 0
            "points",       // 1
            "bid_date",     // 2
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "bid_date";
        const orderDir = req?.body?.order || -1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const gameDB_id = req?.body?.gameDB_id?.trim();
        const bid_revert_date = req?.body?.date?.trim();

        if (!gameDB_id || !bid_revert_date) {
            return res.status(400).json({ success: false, msg: 'Missing required fields.' });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid gameDB_id.' });
        }

        const bidDateStart = moment_timeZone.tz(bid_revert_date, "Asia/Kolkata").startOf('day').toDate();
        const bidDateEnd = moment_timeZone.tz(bid_revert_date, "Asia/Kolkata").endOf('day').toDate();

        // Build aggregation
        const aggregationPipeline = [
            {
                $match: {
                    bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                }
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            {
                $unwind: {
                    path: '$user',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $addFields: {
                    user_name: "$user.user_name"
                }
            }
        ];

        // Add search filter
        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = new RegExp(`^${searchValue}`, 'i');

            aggregationPipeline.push({
                $match: {
                    $or: isNumeric
                        ? [
                            {
                                $expr: {
                                    $regexMatch: {
                                        input: { $toString: "$points" },
                                        regex: regexValue,
                                        options: 'i'
                                    }
                                }
                            }
                        ]
                        : [
                            {
                                user_name: { $regex: regexValue }
                            }
                        ]
                }
            });
        }

        aggregationPipeline.push(
            {
                $project: {
                    points: 1,
                    userDB_id: 1,
                    bid_date: 1,
                    user_name: 1
                }
            },
            {
                $sort: { [orderField]: orderDir }
            },
            {
                $facet: {
                    data: [
                        { $skip: skip },
                        { $limit: limit }
                    ],
                    totalCount: [
                        { $count: "count" }
                    ]
                }
            }
        );

        const result = await gali_disswar_bid_history_module.aggregate(aggregationPipeline);

        const totalFiltered = result[0]?.totalCount[0]?.count || 0;
        let results = result[0]?.data || [];

        results = results?.map(item => ({
            ...item,
            bid_date: formatDateToDDMMYYYY(item.bid_date)
        }));

        res.json({
            recordsFiltered: totalFiltered,
            data: results,
            limit
        });

    } catch (err) {
        console.error("getgalidisswarBidRevertData error:", err);
        res.status(500).json({
            success: false,
            msg: 'Something went wrong.'
        });
    }
};

const getUserProfile = async (req, res) => {
    try {
        let { userDB_id } = req.params
        let userData = await user_module.aggregate([
            {
                $lookup: {
                    localField: '_id',
                    foreignField: 'userDB_id',
                    from: 'user_bank_details',
                    as: 'userBankDetails'
                }
            },
            {
                $lookup: {
                    localField: '_id',
                    foreignField: 'userDB_id',
                    from: 'user_address',
                    as: 'userAddress'
                }
            },
            {
                $match: {
                    _id: new mongoose.Types.ObjectId(userDB_id)
                }
            },
            {
                $project: {
                    unique_jwt_token: 0
                }
            }
        ])
        userData = userData.map((v) => ({
            ...v,
            insert_date: formatDateToDDMMYYYY(v.insert_date) + " , " + get12HoursTimeFromISO(v.insert_date),
            last_update: formatDateToDDMMYYYY(v.last_update) + " , " + get12HoursTimeFromISO(v.last_update)
        }))
        return res.json({
            success: true,
            userData: userData[0]
        })
    } catch (err) {
        console.error(err);
        res.status(500).json({
            success: false,
            msg: 'Something went wrong.'
        });
    }
};

const userReferralTableGridData = async (req, res) => {
    try {
        const fields = ["refer_to.user_name", "bonus", "insert_date"];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;

        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const { userDB_id } = req.params;

        console.log("req.params", req.params.userDB_id)

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid userDB_id." });
        }

        const pipeline = [
            {
                $match: { refer_by: new mongoose.Types.ObjectId(userDB_id) }
            },
            {
                $lookup: {
                    from: "users",
                    localField: "refer_to",
                    foreignField: "_id",
                    as: "refer_to"
                }
            },
            { $unwind: "$refer_to" },
            {
                $project: {
                    bonus: 1,
                    insert_date: 1,
                    "refer_to.user_name": 1,
                }
            }
        ];

        if (searchValue) {
            const regex = new RegExp(`^${searchValue}`, "i");
            pipeline.push({
                $match: {
                    $or: [
                        { "refer_to.user_name": { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$bonus" },
                                    regex: regex
                                }
                            }
                        }
                    ]
                }
            }
            );
        }

        const pipelineWithSortPaginate = [
            ...pipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            refer_details_module.aggregate(pipelineWithSortPaginate),
            refer_details_module.aggregate([
                ...pipeline,
                { $count: "total" }
            ])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((rs) => ({
            refer_to: rs.refer_to?.user_name || "-",
            bonus: rs.bonus || 0,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)}`
        }));

        return res.json({
            recordsFiltered: totalFiltered,
            data,
            limit
        });
    } catch (err) {
        console.error("Error in userReferralTableGridData:", err);
        return res.status(500).json({ success: false, msg: "Something went wrong." });
    }
};

// pending for payment getway automatic
const userAddFundReqTableGridData = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        let fields = [
            "amount",
            "tx_request_number",
            "payment_method",
            "txn_ref",
            "reject_remark",
            "fund_payment_receipt",
            "deposit_type",
            "insert_date",
            "fund_status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const skip = !req.body.searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchValue = req.body.searchValue?.trim() || "";
        const { userDB_id } = req.params;

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid userDB_id." });
        }

        const baseMatch = { userDB_id: new mongoose.Types.ObjectId(userDB_id) };

        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$fund_status" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$deposit_type" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { txn_ref: { $regex: `^${searchValue}`, $options: 'i' } },
                        { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
                        { payment_method: { $regex: `^${searchValue}`, $options: 'i' } },
                        { reject_remark: { $regex: `^${searchValue}`, $options: 'i' } },
                    ]
                };
            }
        }

        const pipeline = [
            { $match: { ...baseMatch, ...searchQuery } },
            {
                $project: {
                    amount: 1,
                    tx_request_number: 1,
                    reject_remark: 1,
                    deposit_type: 1,
                    payment_method: 1,
                    txn_ref: 1,
                    fund_status: 1,
                    insert_date: 1,
                    deposit_type: 1,
                    fund_payment_receipt: 1,
                    isAction: {
                        $cond: [
                            { $ne: ['$fund_status', 0] },
                            0,
                            1
                        ]
                    }
                }
            }
        ];

        const pipelineWithPagination = [
            ...pipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            add_funds_module.aggregate(pipelineWithPagination),
            add_funds_module.aggregate([...pipeline, { $count: "total" }])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((rs) => ({
            ...rs,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
            receipt_url: rs?.fund_payment_receipt && baseUrl ? `${baseUrl}/file/uploads/images/${rs.fund_payment_receipt}` : null
        }));

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("Error in userAddFundReqTableGridData:", err);
        return res.status(500).json({ success: false, msg: "Something went wrong." });
    }
};

// pending for payment getway automatic
const userWithdrawFundReqTableGridData = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        let fields = [
            "user_name",
            "amount",
            "tx_request_number",
            "payment_method",
            "remark",
            "fund_payment_receipt",
            "withdraw_type",
            "insert_date",
            "fund_status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const skip = !req.body.searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchValue = req.body.searchValue?.trim() || "";
        const { userDB_id } = req.params;

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid userDB_id." });
        }

        const baseMatch = { userDB_id: new mongoose.Types.ObjectId(userDB_id) };

        let searchQuery = {};

        const pipeline = [
            { $match: { ...baseMatch, ...searchQuery } },
            {
                $project: {
                    fund_payment_receipt: 1,
                    fund_status: 1,
                    remark: 1,
                    payment_method: 1,
                    tx_request_number: 1,
                    amount: 1,
                    withdraw_type: 1,
                    insert_date: 1,
                    paytm_number: 1,
                    ac_holder_name: 1,
                    ac_number: 1,
                    google_pay_number: 1,
                    phone_pay_number: 1,
                    isAction: {
                        $cond: [
                            { $in: ["$fund_status", [1, 2]] },
                            0,
                            1
                        ]
                    }
                }
            }
        ];

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$fund_status" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$payment_method" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$withdraw_type" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$payment_method" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$ac_number" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$paytm_number" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$google_pay_number" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$phone_pay_number" },
                                    regex: `^${searchValue}`,
                                    options: "i"
                                }
                            }
                        },
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { remark: { $regex: `^${searchValue}`, $options: 'i' } },
                        { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
                        { bank_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { branch_address: { $regex: `^${searchValue}`, $options: 'i' } },
                        { ac_holder_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { ifsc_code: { $regex: `^${searchValue}`, $options: 'i' } },
                    ]
                };
            }
        }

        const pipelineWithPagination = [
            ...pipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            withdraw_fund_request_module.aggregate(pipelineWithPagination),
            withdraw_fund_request_module.aggregate([...pipeline, { $count: "total" }])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((rs) => {
            let method = '';
            if (rs.payment_method === 1) {
                method = `A/c Transfer (${rs.ac_number})(${rs.ac_holder_name})`;
            } else if (rs.payment_method === 2) {
                method = `Paytm (${rs.paytm_number})`;
            } else if (rs.payment_method === 3) {
                method = `Google Pay (${rs.google_pay_number})`;
            } else if (rs.payment_method === 4) {
                method = `PhonePay (${rs.phone_pay_number})`;
            }
            return {
                ...rs,
                payment_method: method,
                insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
                receipt_url: rs?.fund_payment_receipt && baseUrl ? `${baseUrl}/uploads/withdrawal-approvals/${rs.fund_payment_receipt}` : null
            }
        });

        let userWallet_balance = await user_module.findOne(
            { _id: userDB_id },
            { wallet_balance: 1, _id: 0 }
        );

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit,
            userWallet_balance: userWallet_balance?.wallet_balance || 0
        });

    } catch (err) {
        console.error("Error in userWithdrawFundReqTableGridData:", err);
        return res.status(500).json({ success: false, msg: "Something went wrong." });
    }
};

const userBitHistoryDataReqTableGridData = async (req, res) => {
    try {
        const fields = [
            "game_name",
            "digit_text",
            "session",
            "digits",
            "closedigits",
            "points",
            "insert_date",
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const skip = !req.body.searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchValue = req.body.searchValue?.trim() || "";
        const { userDB_id } = req.params;

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid userDB_id." });
        }

        const baseMatch = { userDB_id: new mongoose.Types.ObjectId(userDB_id) };

        const pipeline = [
            { $match: baseMatch },
            {
                $project: {
                    game_name: 1,
                    digit_text: 1,
                    session: 1,
                    digits: 1,
                    closedigits: 1,
                    points: 1,
                    insert_date: 1,
                    pana: 1
                }
            }
        ];

        if (searchValue) {
            const regex = new RegExp(`^${searchValue}`, "i");
            pipeline.push({
                $match: {
                    $or: [
                        { game_name: { $regex: regex } },
                        { digit_text: { $regex: regex } },
                        { session: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$digits" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$closedigits" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...pipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            bid_history_module.aggregate(pipelineWithPagination),
            bid_history_module.aggregate([...pipeline, { $count: "total" }])
        ]);

        console.log("winning history result", results)

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((rs) => ({
            ...rs,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
        }));

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("Error in userWithdrawFundReqTableGridData:", err);
        return res.status(500).json({ success: false, msg: "Something went wrong." });
    }
};

const userWalletTransactionHistoryDataReqTableGridData = async (req, res) => {
    // console.log("Params", req.params);
    // console.log("admin user", req.admin);

    try {
        const fields = [
            "_id",
            "",
            "amount",
            "transaction_note",
            "transfer_note",
            "insert_date",
            "tx_request_number",
        ];

        const limit = parseInt(req.body?.length) || 10;
        const page = parseInt(req.body?.start) || 1;
        const skip = !req.body?.searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body?.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body?.order) || -1;
        const searchValue = req.body?.searchValue?.trim() || "";
        const type = req.body?.type || null;
        const { userDB_id } = req.params;



        // console.log("userDB_id", userDB_id);
        console.log("index and odr", fieldIndex, orderField);

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid userDB_id." });
        }

        const baseMatch = { userDB_id: new mongoose.Types.ObjectId(userDB_id) };
        if (type) {
            baseMatch.transaction_type = type;
        }

        const pipeline = [
            { $match: baseMatch },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    amount: 1,
                    transaction_note: 1,
                    transfer_note: 1,
                    insert_date: 1,
                    before_wallet: 1,
                    amount_status: 1,
                    tx_request_number: 1,
                    transaction_type: 1,
                    admin_name: 1,
                    admin_type: 1,
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile",
                }
            }
        ];

        if (searchValue) {
            const regex = new RegExp(`^${searchValue}`, "i");
            pipeline.push({
                $match: {
                    $or: [
                        { transaction_note: { $regex: regex } },
                        { transfer_note: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$tx_request_number" },
                                    regex
                                }
                            }
                        },
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...pipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            wallet_trans_history_module.aggregate(pipelineWithPagination),
            wallet_trans_history_module.aggregate([...pipeline, { $count: "total" }])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((rs) => ({
            ...rs,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
        }));

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("Error in useruserWalletTransactionHistoryHistoryDataReqTableGridData:", err);
        return res.status(500).json({ success: false, msg: "Something went wrong." });
    }
};

const userWinningHistoryDataReqTableGridData = async (req, res) => {
    try {
        const fields = [
            "points",
            "game_name",
            "bid_tx_id",
            "insert_date",
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const skip = !req.body.searchValue ? (page - 1) * limit : 0;
        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchValue = req.body.searchValue?.trim() || "";
        const { userDB_id } = req.params;

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid userDB_id." });
        }

        const baseMatch = { userDB_id: new mongoose.Types.ObjectId(userDB_id), pay_status: { $eq: 1 } };

        const pipeline = [
            { $match: baseMatch },
            {
                $project: {
                    points: 1,
                    game_name: 1,
                    bid_tx_id: 1,
                    insert_date: 1,
                    pay_status: 1
                }
            }
        ];

        if (searchValue) {
            const regex = new RegExp(`^${searchValue}`, "i");
            pipeline.push({
                $match: {
                    $or: [
                        { game_name: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...pipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            bid_history_module.aggregate(pipelineWithPagination),
            bid_history_module.aggregate([...pipeline, { $count: "total" }])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((rs) => ({
            ...rs,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
        }));

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("Error in userWinningHistoryDataReqTableGridData:", err);
        return res.status(500).json({ success: false, msg: "Something went wrong." });
    }
};

const changeSecurityPin = async (req, res) => {
    try {
        let { userDB_id = "", security_pin = "" } = req?.body || {};

        userDB_id = toStr(userDB_id);
        security_pin = Number(toStr(security_pin));

        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'userDB_id is required' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid userDB_id' });
        }

        if (!security_pin) {
            return res.status(400).json({ success: false, msg: 'Security pin is required' });
        }

        const pinRegex = /^\d{4}$/;
        if (!pinRegex.test(security_pin)) {
            return res.status(400).json({ success: false, msg: 'Security pin must be exactly 4 digits' });
        }

        const userExists = await user_module.exists({ _id: userDB_id });
        if (!userExists) {
            return res.status(404).json({ success: false, msg: 'User not found' });
        }

        await user_module.updateOne(
            { _id: userDB_id },
            { $set: { security_pin } }
        );

        await user_device_record_module.updateOne(
            { userDB_id: userDB_id },
            { $set: { security_pin_status: 1 } }
        );

        return res.json({
            success: true,
            security_pin,
            msg: 'Security PIN successfully changed'
        });

    } catch (err) {
        console.error('Error in changeSecurityPin:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal Server Error'
        });
    }
};

// pending for payment getway automatic
const withdrawBalanceUserWallet = async (req, res) => {
    const session = await mongoose.startSession(); // Correct session init
    try {
        session.startTransaction();

        let { userDB_id = "", amount = "" } = req?.body || {};

        userDB_id = toStr(userDB_id);
        const withdrawAmount = Number(toStr(amount));

        // Basic Validations
        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'userDB_id is required' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid userDB_id' });
        }

        if (!withdrawAmount || isNaN(withdrawAmount) || withdrawAmount <= 0) {
            return res.status(400).json({ success: false, msg: 'Valid withdrawal amount is required' });
        }

        // Get user
        const user = await user_module.findOne({ _id: userDB_id }).session(session);
        if (!user) {
            return res.status(404).json({ success: false, msg: 'User not found' });
        }

        if (user.wallet_balance < withdrawAmount) {
            return res.status(400).json({ success: false, msg: 'Insufficient wallet balance' });
        }

        // Deduct balance
        await user_module.updateOne(
            { _id: userDB_id },
            { $inc: { wallet_balance: -withdrawAmount } },
            { session }
        );

        // Add to wallet transaction history
        const request_number = uniqRandom();
        await wallet_trans_history_module.create(
            [{
                userDB_id,
                amount: withdrawAmount,
                transaction_type: 2, // 2 = Withdraw
                transaction_note: 'Amount Withdrawn By Admin',
                amount_status: 2,    // 2 = Withdraw type
                tx_request_number: request_number,
            }],
            { session }
        );

        await session.commitTransaction();
        session.endSession();

        return res.json({ success: true, msg: 'Amount successfully withdrawn' });

    } catch (err) {
        await session.abortTransaction();
        session.endSession();
        console.error('Error in withdrawBalanceUserWallet:', err);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const rejectFundRequest = async (req, res) => {
    try {
        const fund_requestDB_id = (req?.body?.transactionDB_id || '').trim();
        const remark = (req?.body?.remark || '').trim();

        if (!fund_requestDB_id || !remark) {
            return res.json({ success: false, msg: "Fund request ID or remark are required" });
        }

        if (!mongoose.isValidObjectId(fund_requestDB_id)) {
            return res.json({ success: false, msg: "Invalid fund request ID" });
        }

        const fundRequest = await add_funds_module.findById(fund_requestDB_id);
        if (!fundRequest) {
            return res.json({ success: false, msg: "Request not found" });
        }

        const { userDB_id, request_amount: amount } = fundRequest;

        fundRequest.fund_status = 2;
        fundRequest.remark = remark;
        await fundRequest.save();

        const notification = new user_notification_module({
            userDB_id,
            msg: `Sorry, Your fund request of amount ${amount} is rejected.`,
        });
        await notification.save();

        return res.json({
            success: true,
            request_status: "Rejected",
            msg: "Request Successfully Rejected"
        });

    } catch (error) {
        console.error(error);
        return res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};

const adminLogout = async (req, res) => {
    try {
        res.clearCookie("unique_jwt_token", {
            httpOnly: true,
            signed: true,
            secure: process.env.NODE_ENV === 'production'
        });

        return res.json({
            success: true,
            msg: "Logout successful",
        });

    } catch (error) {
        console.error("Error in adminLogout:", error);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong during logout",
        });
    }
};

let isRefundProcessing = false;
const refundAmount = async (req, res) => {
    if (isRefundProcessing) {
        return res.json({ success: false, already_msg: "Refund process is already in progress." });
    }

    isRefundProcessing = true;

    let attempts = 0;
    const maxAttempts = 3;

    while (attempts < maxAttempts) {
        const session = await mongoose.startSession();
        try {
            attempts++;
            await session.startTransaction();

            const gameDB_id = req.body.gameDB_id;
            const bid_revert_date = moment_timeZone.tz(req.body.bid_revert_date, "Asia/Kolkata");
            const bidDateStart = bid_revert_date.clone().startOf('day').toDate();
            const bidDateEnd = bid_revert_date.clone().endOf('day').toDate();

            const bids = await bid_history_module.aggregate([
                {
                    $match: {
                        bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0
                    }
                },
                {
                    $lookup: {
                        from: 'users',
                        localField: 'userDB_id',
                        foreignField: '_id',
                        as: 'user'
                    }
                },
                { $unwind: "$user" },
                {
                    $project: {
                        _id: 1,
                        points: 1,
                        game_name: 1,
                        pana: 1,
                        userDB_id: 1,
                        user_wallet_balance: "$user.wallet_balance"
                    }
                }
            ]);

            if (!bids.length) {
                await session.abortTransaction();
                session.endSession();
                isRefundProcessing = false;
                return res.status(400).json({ success: false, msg: "No pending bids found." });
            }

            for (const bid of bids) {
                const { userDB_id, _id: bid_id, points, game_name, pana } = bid;

                // Step 1: Update user's wallet
                await user_module.updateOne(
                    { _id: userDB_id },
                    { $inc: { wallet_balance: points } },
                    { session }
                );

                // Step 2: Insert into wallet transaction history
                await wallet_trans_history_module.create([{
                    userDB_id,
                    amount: points,
                    transaction_type: 1,
                    transaction_note: `Bid Amount is reverted for ${game_name}-${pana}`,
                    amount_status: 7,
                    tx_request_number: uniqRandom(15),
                }], { session });

                // Step 3: Update bid pay_status
                await bid_history_module.updateOne(
                    { _id: bid_id },
                    { $set: { pay_status: 3 } },
                    { session }
                );
            }

            await session.commitTransaction();
            session.endSession();
            isRefundProcessing = false;

            return res.json({
                success: true,
                msg: "All refundable bids processed successfully."
            });

        } catch (error) {
            await session.abortTransaction();
            session.endSession();

            console.error(`Attempt ${attempts} failed:`, error);

            if (attempts >= maxAttempts) {
                isRefundProcessing = false;
                return res.status(500).json({
                    success: false,
                    msg: "Failed after 3 retry attempts."
                });
            }

            // Optional: Wait a little before retrying (e.g., 500ms)
            await new Promise(resolve => setTimeout(resolve, 500));
        }
    }
};

let isStarlineRefundProcessing = false;
const starlineRefundAmount = async (req, res) => {
    if (isStarlineRefundProcessing) {
        return res.json({ success: false, already_msg: "Refund process is already in progress." });
    }

    isStarlineRefundProcessing = true;

    let attempts = 0;
    const maxAttempts = 3;

    while (attempts < maxAttempts) {
        const session = await mongoose.startSession();
        try {
            attempts++;
            await session.startTransaction();

            const gameDB_id = req.body.gameDB_id;
            const bid_revert_date = moment_timeZone.tz(req.body.bid_revert_date, "Asia/Kolkata");
            const bidDateStart = bid_revert_date.clone().startOf('day').toDate();
            const bidDateEnd = bid_revert_date.clone().endOf('day').toDate();

            const bids = await starline_bid_history_module.aggregate([
                {
                    $match: {
                        bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0
                    }
                },
                {
                    $lookup: {
                        from: 'users',
                        localField: 'userDB_id',
                        foreignField: '_id',
                        as: 'user'
                    }
                },
                { $unwind: "$user" },
                {
                    $project: {
                        _id: 1,
                        points: 1,
                        game_name: 1,
                        pana: 1,
                        userDB_id: 1,
                        user_wallet_balance: "$user.wallet_balance"
                    }
                }
            ]);

            if (!bids.length) {
                await session.abortTransaction();
                session.endSession();
                isStarlineRefundProcessing = false;
                return res.status(400).json({ success: false, msg: "No pending bids found." });
            }

            for (const bid of bids) {
                const { userDB_id, _id: bid_id, points, game_name, pana } = bid;

                // Step 1: Update user's wallet
                await user_module.updateOne(
                    { _id: userDB_id },
                    { $inc: { wallet_balance: points } },
                    { session }
                );

                // Step 2: Insert into wallet transaction history
                await wallet_trans_history_module.create([{
                    userDB_id,
                    amount: points,
                    transaction_type: 1,
                    transaction_note: `Bid Amount is reverted for ${game_name}-${pana}`,
                    amount_status: 7,
                    tx_request_number: uniqRandom(15),
                }], { session });

                // Step 3: Update bid pay_status
                await starline_bid_history_module.updateOne(
                    { _id: bid_id },
                    { $set: { pay_status: 3 } },
                    { session }
                );
            }

            await session.commitTransaction();
            session.endSession();
            isStarlineRefundProcessing = false;

            return res.json({
                success: true,
                msg: "All refundable bids processed successfully."
            });

        } catch (error) {
            await session.abortTransaction();
            session.endSession();

            console.error(`Attempt ${attempts} failed:`, error);

            if (attempts >= maxAttempts) {
                isStarlineRefundProcessing = false;
                return res.status(500).json({
                    success: false,
                    msg: "Failed after 3 retry attempts."
                });
            }

            // Optional: Wait a little before retrying (e.g., 500ms)
            await new Promise(resolve => setTimeout(resolve, 500));
        }
    }
};

let isGalidisswarRefundProcessing = false;
const galidisswarRefundAmount = async (req, res) => {
    if (isGalidisswarRefundProcessing) {
        return res.json({ success: false, already_msg: "Refund process is already in progress." });
    }

    isGalidisswarRefundProcessing = true;

    let attempts = 0;
    const maxAttempts = 3;

    while (attempts < maxAttempts) {
        const session = await mongoose.startSession();
        try {
            attempts++;
            await session.startTransaction();

            const gameDB_id = req.body.gameDB_id;
            const bid_revert_date = new Date(req.body.bid_revert_date);
            const bidDateStart = new Date(bid_revert_date.setHours(0, 0, 0, 0));
            const bidDateEnd = new Date(bid_revert_date.setHours(23, 59, 59, 999));

            const bids = await gali_disswar_bid_history_module.aggregate([
                {
                    $match: {
                        bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0
                    }
                },
                {
                    $lookup: {
                        from: 'users',
                        localField: 'userDB_id',
                        foreignField: '_id',
                        as: 'user'
                    }
                },
                { $unwind: "$user" },
                {
                    $project: {
                        _id: 1,
                        points: 1,
                        game_name: 1,
                        pana: 1,
                        userDB_id: 1,
                        user_wallet_balance: "$user.wallet_balance"
                    }
                }
            ]);

            if (!bids.length) {
                await session.abortTransaction();
                session.endSession();
                isGalidisswarRefundProcessing = false;
                return res.status(400).json({ success: false, msg: "No pending bids found." });
            }

            for (const bid of bids) {
                const { userDB_id, _id: bid_id, points, game_name, pana } = bid;

                // Step 1: Update user's wallet
                await user_module.updateOne(
                    { _id: userDB_id },
                    { $inc: { wallet_balance: points } },
                    { session }
                );

                // Step 2: Insert into wallet transaction history
                await wallet_trans_history_module.create([{
                    userDB_id,
                    amount: points,
                    transaction_type: 1,
                    transaction_note: `Bid Amount is reverted for ${game_name}-${pana}`,
                    amount_status: 7,
                    tx_request_number: uniqRandom(15),
                }], { session });

                // Step 3: Update bid pay_status
                await gali_disswar_bid_history_module.updateOne(
                    { _id: bid_id },
                    { $set: { pay_status: 3 } },
                    { session }
                );
            }

            await session.commitTransaction();
            session.endSession();
            isGalidisswarRefundProcessing = false;

            return res.json({
                success: true,
                msg: "All refundable bids processed successfully."
            });

        } catch (error) {
            await session.abortTransaction();
            session.endSession();

            console.error(`Attempt ${attempts} failed:`, error);

            if (attempts >= maxAttempts) {
                isGalidisswarRefundProcessing = false;
                return res.status(500).json({
                    success: false,
                    msg: "Failed after 3 retry attempts."
                });
            }

            // Optional: Wait a little before retrying (e.g., 500ms)
            await new Promise(resolve => setTimeout(resolve, 500));
        }
    }
};

const getPredictWinnerList = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            predictionDate,
            gameDB_id,
            session = "",
            selected_open_pana = "",
            selected_close_pana = ""
        } = req.body;

        const fields = [
            "user_name",
            "points",
            "winning_points",
            "pana",
            "bid_tx_id"
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const prediction = moment_timeZone.tz(predictionDate?.trim(), 'Asia/Kolkata');

        const startDate = prediction.clone().startOf('day').toDate();
        const endDate = prediction.clone().endOf('day').toDate();

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const matchFilter = {
            // gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            pay_status: 0,
            insert_date: { $gte: startDate, $lte: endDate },
            session,
        };

        const sumDigits = (str) =>
            str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0);

        const openNumber = sumDigits(selected_open_pana);
        const closeNumber = sumDigits(selected_close_pana);
        const selectedPana = session === 'Open'
            ? parseInt(selected_open_pana, 10)
            : parseInt(selected_close_pana, 10);

        // Add digit-based match logic to aggregation pipeline
        const matchDigitLogic = {
            $match: {
                $expr: {
                    $switch: {
                        branches: [
                            {
                                case: { $eq: ["$pana", "Single Digit"] },
                                then: {
                                    $or: [
                                        { $and: [{ $eq: [session, "Open"] }, { $eq: [{ $toInt: "$digits" }, openNumber] }] },
                                        { $and: [{ $eq: [session, "Close"] }, { $eq: [{ $toInt: "$digits" }, closeNumber] }] }
                                    ]
                                }
                            },
                            {
                                case: { $in: ["$pana", ["Jodi Digit", "Group Jodi", "Red Bracket"]] },
                                then: {
                                    $let: {
                                        vars: {
                                            padded: {
                                                $cond: [
                                                    { $lt: [{ $strLenCP: { $toString: "$digits" } }, 2] },
                                                    { $concat: ["0", { $toString: "$digits" }] },
                                                    { $toString: "$digits" }
                                                ]
                                            }
                                        },
                                        in: {
                                            $and: [
                                                { $eq: [{ $toInt: { $substrCP: ["$$padded", 0, 1] } }, openNumber] },
                                                { $eq: [{ $toInt: { $substrCP: ["$$padded", 1, 1] } }, closeNumber] }
                                            ]
                                        }
                                    }
                                }
                            },
                            {
                                case: { $eq: ["$pana", "Half Sangam"] },
                                then: {
                                    $and: [
                                        { $eq: [{ $toInt: "$digits" }, openNumber] },
                                        { $eq: [{ $toInt: "$closedigits" }, closeNumber] }
                                    ]
                                }
                            },
                            {
                                case: { $eq: ["$pana", "Full Sangam"] },
                                then: {
                                    $and: [
                                        { $eq: [{ $toInt: "$digits" }, openNumber] },
                                        { $eq: [{ $toInt: "$closedigits" }, closeNumber] }
                                    ]
                                }
                            },
                            {
                                case: {
                                    $in: [
                                        "$pana",
                                        ["Single Pana", "Double Pana", "Triple Pana"]
                                    ]
                                },
                                then: {
                                    $eq: [{ $toInt: "$digits" }, selectedPana]
                                }
                            }
                        ],
                        default: false
                    }
                }
            }
        };

        const basePipeline2 = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            {
                $lookup: {
                    from: "games",
                    localField: "gameDB_id",
                    foreignField: "_id",
                    as: "gameData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    points: 1,
                    winning_points: 1,
                    pana: 1,
                    bid_tx_id: 1,
                    pay_status: 1,
                    digits: 1,
                    insert_date: 1,
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile"
                }
            },
            // matchDigitLogic
        ];

        const basePipeline = [...basePipeline2];
        basePipeline.push(matchDigitLogic);

        // console.log("pipeline 1 2 -", basePipeline,basePipeline2)


        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$winning_points" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr, total_bid, total_win] = await Promise.all([
            bid_history_module.aggregate(pipelineWithPagination),
            bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
            bid_history_module.aggregate([...basePipeline2, {
                $group: {
                    _id: null,
                    total_bid_amount: { $sum: "$points" }
                }
            }]),
            bid_history_module.aggregate([
                ...basePipeline,
                {
                    $group: {
                        _id: null,
                        total_winning_points: { $sum: "$winning_points" },
                    }
                }
            ])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        // const total_winning_points = totalsArr[0]?.total_winning_points || 0;
        // const total_bid_amount = totalsArr[0]?.total_bid_amount || 0;
        const total_bid_amount = total_bid[0]?.total_bid_amount || 0;
        const total_winning_points = total_win[0]?.total_winning_points || 0;

        console.log("win bid amount-", total_bid_amount, total_winning_points)

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            total_winning_points,
            total_bid_amount,
            data: results,
            limit
        });

    } catch (err) {

        console.error("getPredictWinnerList Error:", err);
        return res.status(500).json({ success: false, msg: "Server error: " + err.message });
    }
};

const updateBid = async (req, res) => {
    try {
        let { digit = "", bidDB_id = "", collectionName = "" } = req.body || {};

        // Convert to string and trim
        digit = String(digit).trim();
        bidDB_id = String(bidDB_id).trim();

        // Validate inputs
        if (!bidDB_id) {
            return res.status(400).json({ success: false, msg: 'Missing bidDB_id.' });
        }
        let Model;
        try {
            Model = mongoose.model(collectionName);
        } catch (e) {
            return res.status(400).json({ success: false, msg: 'Invalid collection name' });
        }

        if (!digit) {
            return res.status(400).json({ success: false, msg: 'Digit is required.' });
        }

        if (!/^\d{1,3}$/.test(digit)) {
            return res.status(400).json({ success: false, msg: 'Digit must be 1 to 3 numeric digits.' });
        }

        if (!mongoose.isValidObjectId(bidDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid bidDB_id.' });
        }

        const updateResult = await Model.updateOne(
            { _id: bidDB_id },
            { $set: { digits: digit } }
        );

        if (updateResult.modifiedCount === 0) {
            return res.status(404).json({ success: false, msg: 'Bid not found or digit unchanged.' });
        }

        return res.json({
            success: true,
            digit,
            msg: 'Bid updated successfully.'
        });
    } catch (err) {
        console.error('updateBid Error:', err);
        return res.status(500).json({ success: false, msg: 'Server error. Please try again later.' });
    }
};

const getBidHistoryData = async (req, res) => {
    try {
        const {
            length = 100,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            // predictionDate,
            start_date,
            end_date,
            selected_gameDB_id,
            selected_gameType,
            min_amount
        } = req.body;


        const fields = [
            "user_name",
            "bid_tx_id",
            "game_name",
            "pana",
            "session",
            "digits",
            "digits",
            "digits",
            "digits",
            "points",
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) * limit : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        // console.log("req.body in getBidHistoryData", req.body);

        if (!start_date || !end_date) {
            return res.status(200).json({ success: false, msg: " Starting and ending are required" });
        }


        const SelectedendDate = moment_timeZone.tz(end_date.trim(), ["DD-MM-YYYY", "YYYY-MM-DD"], "Asia/Kolkata")
        const SelectedstartDate = moment_timeZone.tz(start_date.trim(), ["DD-MM-YYYY", "YYYY-MM-DD"], "Asia/Kolkata")
        const startDate = SelectedstartDate.clone().startOf("day").toDate();
        const endDate = SelectedendDate.clone().endOf("day").toDate();




        console.log("startDate, endDate", startDate, endDate);

        // console.log("xx, xy", startDate, endDate);
        // start date should be less than or equal to end date


        if (startDate > endDate) {
            return res.status(200).json({ success: false, msg: "Start date can not be greater than end date." });
        }

        const matchFilter = {
            // pay_status: 0,
            bid_date: { $gte: startDate, $lte: endDate },
        };

        if (min_amount !== "" && !isNaN(min_amount) && Number(min_amount) > 0) {
            matchFilter.points = { $gte: Number(min_amount) };
        }


        if (selected_gameDB_id) {
            if (!mongoose.isValidObjectId(selected_gameDB_id)) {
                console.log("gameDB ", selected_gameDB_id);
                return res.status(400).json({ success: false, msg: "Invalid selected_gameDB_id." });
            }
            matchFilter.gameDB_id = new mongoose.Types.ObjectId(selected_gameDB_id)
        }


        if (selected_gameType !== "" && selected_gameType !== 'all') {
            matchFilter.pana = selected_gameType
        }


        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    game_name: 1,
                    pana: 1,
                    session: 1,
                    digits: 1,
                    closedigits: 1,
                    points: 1,
                    bid_tx_id: 1,
                    bid_date: 1,
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name"
                }
            },
        ];

        // console.log("basepipeline", basePipeline);

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        { game_name: { $regex: regex } },
                        { session: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$digits" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        // console.log("basePipeline in getBidHistoryData", pipelineWithPagination);

        const [results, totalCountArr] = await Promise.all([
            bid_history_module.aggregate(pipelineWithPagination),
            bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
        ]);

        // console.log("results in getBidHistoryData", results);

        // console.log("results in totalCountArr", totalCountArr);


        const totalFiltered = totalCountArr[0]?.total || 0;
        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        const data = results.map((v) => {
            const common = {
                _id: v._id,
                game_name: v.game_name,
                pana: v.pana,
                points: v.points,
                session: v.session,
                bid_tx_id: v.bid_tx_id,
                bid_date: v.bid_date,
                user_name: v.user_name,
            };

            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };

                case 'Jodi Digit':
                case 'Group Jodi':
                case 'Red Bracket': {
                    const padded = String(v.digits).padStart(2, '0');
                    return {
                        ...common,
                        open_digit: padded[0],
                        close_digit: padded[1],
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
                }

                case 'Full Sangam':
                    return {
                        ...common,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                    };

                case 'Half Sangam':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                        close_pana: v.session === 'Open' ? v.closedigits : 'N/A',
                    };

                case 'Single Pana':
                case 'Double Pana':
                case 'Triple Pana':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? sumDigits_with_reminder(String(v.digits)) : 'N/A',
                        close_digit: v.session === 'Close' ? sumDigits_with_reminder(String(v.digits)) : 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.digits : v.closedigits,
                    };

                default:
                    return {
                        ...common,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
            }
        });

        // console.log("data in getBidHistoryData", data);

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("getBidHistoryData Error:", err);
        return res.status(500).json({ success: false, msg: "Server error: " + err.message });
    }
};

const updateBid_with_property = async (req, res) => {
    try {
        let {
            digit = "",
            open_digit = "",
            close_digit = "",
            open_pana = "",
            close_pana = "",
            pana_digit = "",
            full_sangam = "",
            bidDB_id = ""
        } = req.body || {};

        bidDB_id = String(bidDB_id).trim();

        // Validate bidDB_id
        if (!bidDB_id) {
            return res.status(400).json({ success: false, msg: "Missing bidDB_id." });
        }

        if (!mongoose.isValidObjectId(bidDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid bidDB_id." });
        }

        // Build updateFields object
        const updateFields = {};

        // Priority-wise conditional logic
        if (digit) {
            updateFields.digits = digit;
        }

        if (open_pana && close_digit) {
            updateFields.digits = close_digit;
            updateFields.closedigits = open_pana;
        }

        if (open_digit && close_pana) {
            updateFields.digits = open_digit;
            updateFields.closedigits = close_pana;
        }

        if (pana_digit) {
            updateFields.digits = pana_digit;
        }

        if (full_sangam) {
            const find = await bid_history_module.findById(bidDB_id);

            if (!find) {
                return res.status(404).json({ success: false, msg: "Bid not found." });
            }

            if (find.session === 'Open') {
                updateFields.digits = full_sangam;
            } else {
                updateFields.closedigits = full_sangam;
            }
        }

        if (Object.keys(updateFields).length === 0) {
            return res.status(400).json({
                success: false,
                msg: "No valid fields provided for update."
            });
        }

        const updateResult = await bid_history_module.updateOne(
            { _id: bidDB_id },
            { $set: updateFields }
        );

        if (updateResult.modifiedCount === 0) {
            return res.status(404).json({
                success: false,
                msg: "Bid not found or no changes made."
            });
        }

        return res.json({
            success: true,
            msg: "Bid updated successfully.",
            updatedFields: updateFields
        });
    } catch (err) {
        console.error("updateBid_with_property Error:", err);
        return res.status(500).json({
            success: false,
            msg: "Server error. Please try again later."
        });
    }
};

const getCustomerSellReport = async (req, res) => {
    try {
        const { gameDB_id, predictionDate, gameType = "all", session } = req.body;

        if (!gameDB_id) {
            return res.status(400).json({ success: false, msg: "Missing gameDB_id." });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        let baseFilter = {
            gameDB_id,
            bid_date: { $gte: startDate, $lte: endDate }
        };

        if (gameType !== 'Full Sangam' && gameType !== 'Jodi Digit') {
            baseFilter.session = session
        }

        if (gameType !== "all") {
            baseFilter.pana = gameType;
        }

        const results = await bid_history_module.find(baseFilter);

        const data = {
            single_digit: [],
            jodi_digit: [],
            group_jodi: [],
            red_bracket: [],
            single_pana: [],
            double_pana: [],
            triple_pana: [],
            half_sangam: [],
            full_sangam: [],
        };

        // Helper to aggregate points
        const aggregatePoints = (category, digit, points, closedigits) => {
            if (category === "half_sangam") {
                if (session === 'Open') {
                    const existing = data[category].find((item) => item.open_digit === digit && item.close_pana === closedigits);
                    if (existing) {
                        existing.points += points
                    } else {
                        data[category].push({ open_digit: digit, close_pana: closedigits, points });
                    }
                } else if (session === 'Close') {
                    const existing = data[category].find((item) => item.close_digit === digit && item.open_pana === closedigits);
                    if (existing) {
                        existing.points += points
                    } else {
                        data[category].push({ close_digit: digit, open_pana: closedigits, points });
                    }
                }
            } else if (category === "full_sangam") {
                const existing = data[category].find((item) => item.open_pana === digit && item.close_pana === closedigits);
                if (existing) {
                    existing.points += points
                } else {
                    data[category].push({ open_pana: digit, close_pana: closedigits, points });
                }
            } else {
                const existing = data[category].find((item) => item.digit === digit);
                if (existing) {
                    existing.points += points;
                } else {
                    data[category].push({ digit, points });
                }
            }
        };

        results.forEach((v) => {
            const digit = v.digits;
            const closedigits = v?.closedigits || 0;
            const points = Number(v.points) || 0;

            switch (v.pana) {
                case "Single Digit":
                    aggregatePoints("single_digit", digit, points);
                    break;
                case "Jodi Digit":
                    aggregatePoints("jodi_digit", digit, points);
                    break;
                case 'Group Jodi':
                    aggregatePoints("group_jodi", digit, points);
                    break;
                case 'Red Bracket':
                    aggregatePoints("red_bracket", digit, points);
                    break;
                case "Single Pana":
                    aggregatePoints("single_pana", digit, points);
                    break;
                case "Double Pana":
                    aggregatePoints("double_pana", digit, points);
                    break;
                case "Triple Pana":
                    aggregatePoints("triple_pana", digit, points);
                    break;
                case "Half Sangam":
                    aggregatePoints("half_sangam", digit, points, closedigits);
                    break;
                case "Full Sangam":
                    aggregatePoints("full_sangam", digit, points, closedigits);
                    break;
            }
        });

        return res.json({
            success: true,
            data
        });

    } catch (err) {
        console.error("getCustomerSellReport Error:", err);
        return res.status(500).json({ success: false, msg: "Server error. Please try again later." });
    }
};

const getTransferReport = async (req, res) => {
    try {
        const fields = ["sender_name", "receiver_name", "amount", "insert_date"];

        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            searchValue = "",
            transfer_date = ""
        } = req.body;

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchRegex = new RegExp(searchValue.trim(), "i");

        if (!transfer_date) {
            return res.status(400).json({ success: false, msg: "transfer_date is required." });
        }

        const istDate = moment_timeZone.tz(transfer_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const baseMatch = {
            amount_status: 3,
            insert_date: { $gte: startDate, $lte: endDate },
        };

        const basePipeline = [
            { $match: baseMatch },

            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "sender"
                }
            },
            { $unwind: "$sender" },

            {
                $lookup: {
                    from: "wallet_trans_histories",
                    let: { tx: "$tx_request_number" },
                    pipeline: [
                        {
                            $match: {
                                $expr: {
                                    $and: [
                                        { $eq: ["$tx_request_number", "$$tx"] },
                                        { $eq: ["$amount_status", 4] }
                                    ]
                                }
                            }
                        },
                        {
                            $lookup: {
                                from: "users",
                                localField: "userDB_id",
                                foreignField: "_id",
                                as: "receiver"
                            }
                        },
                        { $unwind: "$receiver" }
                    ],
                    as: "receiver_data"
                }
            },
            { $unwind: "$receiver_data" },

            {
                $project: {
                    sender_userDB_id: "$sender.userDB_id",
                    sender_name: "$sender.user_name",
                    receiver_userDB_id: "$receiver_data.receiver.userDB_id",
                    receiver_name: "$receiver_data.receiver.user_name",
                    amount: 1,
                    insert_date: 1,
                    tx_request_number: 1
                }
            }
        ];

        if (searchValue) {
            basePipeline.push({
                $match: {
                    $or: [
                        { sender_name: { $regex: searchRegex } },
                        { receiver_name: { $regex: searchRegex } },
                        { tx_request_number: { $regex: searchRegex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex: searchRegex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, countResult] = await Promise.all([
            wallet_trans_history_module.aggregate(pipelineWithPagination),
            wallet_trans_history_module.aggregate([...basePipeline, { $count: "total" }])
        ]);

        const totalFiltered = countResult?.[0]?.total || 0;

        const data = results.map(item => ({
            ...item,
            insert_date: `${formatDateToDDMMYYYY(item.insert_date)} , ${get12HoursTimeFromISO(item.insert_date)}`
        }));

        const [totalFundResult] = await wallet_trans_history_module.aggregate([
            { $match: baseMatch },
            { $group: { _id: null, total: { $sum: "$amount" } } }
        ]);

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            totalFundResult: totalFundResult?.total || 0,
            data,
            limit
        });

    } catch (err) {
        console.error("getTransferReport Error:", err);
        res.status(500).json({ success: false, msg: "Server error." });
    }
};

// pending
const getWithdrawReportDetails = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const fields = [
            "user_name",
            "amount",
            "tx_request_number",
            "payment_method",
            "remark",
            "fund_payment_receipt",
            "withdraw_type",
            "insert_date",
            "fund_status",
        ];

        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            searchValue = "",
            // previously withdraw_date; now expect two separate dates:
            start_withdraw_date = "",
            end_withdraw_date = ""
        } = req.body;

        const limit = parseInt(length) || 10;
        const page = parseInt(start) || 1;
        const skip = (page - 1) * limit;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchRegex = new RegExp(searchValue.trim(), "i");

        // Validate both start and end dates are provided
        if (!start_withdraw_date || !end_withdraw_date) {
            return res.status(400).json({ success: false, msg: "Both start_withdraw_date and end_withdraw_date are required." });
        }

        // Parse dates in Asia/Kolkata timezone
        const startMoment = moment_timeZone.tz(start_withdraw_date.trim(), 'Asia/Kolkata');
        const endMoment = moment_timeZone.tz(end_withdraw_date.trim(), 'Asia/Kolkata');

        if (!startMoment.isValid() || !endMoment.isValid()) {
            return res.status(400).json({ success: false, msg: "Invalid date format for start_withdraw_date or end_withdraw_date." });
        }

        // Ensure start <= end (optional safety)
        if (startMoment.isAfter(endMoment)) {
            return res.status(400).json({ success: false, msg: "start_withdraw_date must be earlier than or equal to end_withdraw_date." });
        }

        const startDate = startMoment.clone().startOf('day').toDate();
        const endDate = endMoment.clone().endOf('day').toDate();

        const baseMatch = {
            insert_date: { $gte: startDate, $lte: endDate },
        };

        const basePipeline = [
            { $match: baseMatch },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "user"
                }
            },
            { $unwind: "$user" },
            {
                $project: {
                    user_name: '$user.user_name',
                    userDB_id: '$user._id',
                    wallet_balance: '$user.wallet_balance',
                    fund_payment_receipt: 1,
                    fund_status: 1,
                    remark: 1,
                    payment_method: 1,
                    tx_request_number: 1,
                    amount: 1,
                    withdraw_type: 1,
                    insert_date: 1,
                    paytm_number: 1,
                    ac_holder_name: 1,
                    ac_number: 1,
                    google_pay_number: 1,
                    phone_pay_number: 1,
                    isAction: {
                        $cond: [
                            { $in: ["$fund_status", [1, 2]] },
                            0,
                            1
                        ]
                    }
                }
            },
        ];

        if (searchValue) {
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { remark: { $regex: `^${searchValue}`, $options: 'i' } },
                        { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
                        { bank_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { branch_address: { $regex: `^${searchValue}`, $options: 'i' } },
                        { ac_holder_name: { $regex: `^${searchValue}`, $options: 'i' } },


                        { ifsc_code: { $regex: `^${searchValue}`, $options: 'i' } },
                        { $expr: { $regexMatch: { input: { $toString: "$amount" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$fund_status" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$payment_method" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$withdraw_type" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$ac_number" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$paytm_number" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$google_pay_number" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$phone_pay_number" }, regex: searchRegex, options: "i" } } },
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        // const [results, countResult, withdrawAmountData, totalAcceptData, totalRejectData] = await Promise.all([
        //     withdraw_fund_request_module.aggregate(pipelineWithPagination),
        //     withdraw_fund_request_module.aggregate([...basePipeline, { $count: "total" }]),
        //     withdraw_fund_request_module.aggregate([
        //         {
        //             $match: {
        //                 insert_date: { $gte: startDate, $lte: endDate }
        //             }
        //         },
        //         { $group: { _id: null, total: { $sum: "$amount" } } }
        //     ]),
        //     withdraw_fund_request_module.aggregate([
        //         {
        //             $match: {
        //                 fund_status: 1,
        //                 insert_date: { $gte: startDate, $lte: endDate }
        //             }
        //         },
        //         { $group: { _id: null, total: { $sum: "$amount" } } }
        //     ]),
        //     withdraw_fund_request_module.aggregate([
        //         {
        //             $match: {
        //                 fund_status: 2,
        //                 insert_date: { $gte: startDate, $lte: endDate }
        //             }
        //         },
        //         { $group: { _id: null, total: { $sum: "$amount" } } }
        //     ]),
        // ]);

        const [
            results,
            countResult,
            withdrawAmountData,
            statusAmounts
        ] = await Promise.all([
            // Paginated data
            withdraw_fund_request_module.aggregate(pipelineWithPagination),

            // Count total filtered
            withdraw_fund_request_module.aggregate([...basePipeline, { $count: "total" }]),

            // Total withdraw amount
            withdraw_fund_request_module.aggregate([
                { $match: { insert_date: { $gte: startDate, $lte: endDate } } },
                { $group: { _id: null, total: { $sum: "$amount" } } }
            ]),

            // Sum amount grouped by fund_status
            withdraw_fund_request_module.aggregate([
                { $match: { insert_date: { $gte: startDate, $lte: endDate } } },
                { $group: { _id: "$fund_status", total: { $sum: "$amount" } } }
            ])
        ]);

        const totalFiltered = countResult?.[0]?.total || 0;
        const totalWithdrawAmt = withdrawAmountData[0]?.total || 0;
        // console.log("status amount", statusAmounts)

        // Initialize totals
        let totalSuccess = 0;
        let totalPending = 0;
        let totalCanceled = 0;
        let totalProcessing = 0;


        // Map status sums
        (statusAmounts || []).forEach(item => {
            switch (item._id) {
                case 0: totalPending = item.total; break;
                case 1: totalSuccess = item.total; break;
                case 2: totalCanceled = item.total; break;
                case 3: totalProcessing = item.total; break;
            }
        });

        // console.log("totalsuccess, totalcanceled", totalSuccess,totalCanceled)

        const data = results.map(item => {
            let method = "";
            switch (item.payment_method) {
                case 1: method = `A/c Transfer (${item.ac_number})(${item.ac_holder_name})`; break;
                case 2: method = `Paytm (${item.paytm_number})`; break;
                case 3: method = `Google Pay (${item.google_pay_number})`; break;
                case 4: method = `PhonePay (${item.phone_pay_number})`; break;
                default: method = "Unknown";
            }
            return {
                ...item,
                payment_method: method,
                insert_date: item.insert_date
                    ? `${moment_timeZone(item.insert_date).tz('Asia/Kolkata').format('DD-MM-YYYY, hh:mm A')}`
                    : 'N/A',
                receipt_url: item?.fund_payment_receipt && baseUrl
                    ? `${baseUrl}/file/uploads/images/${item.fund_payment_receipt}`
                    : null
            };
        });

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            withdraw_amt: totalWithdrawAmt,
            total_success: totalSuccess,
            total_pending: totalPending,
            total_canceled: totalCanceled,
            total_processing: totalProcessing,
            data,
            limit
        });




    } catch (err) {
        console.error("getWithdrawReportDetails Error:", err);
        res.status(500).json({ status: "error", msg: "Server error." });
    }
};

// pending
const getAutoDepositeHistory = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const fields = [
            "user_name",
            "amount",
            "tx_request_number",
            "payment_method",
            "txn_ref",
            "reject_remark",
            "fund_payment_receipt",
            "deposit_type",
            "insert_date",
            "fund_status",
        ];

        console.log("body-", req.body)

        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            searchValue = "",
            deposit_date = "",
            start_deposit_date,
            end_deposit_date

        } = req.body;

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(req.body.order) || -1;
        const searchRegex = new RegExp(searchValue.trim(), "i");

        if (!start_deposit_date || !end_deposit_date) {
            return res.status(400).json({ success: false, msg: "both start and end deposit date is required." });
        }

        const startMoment = moment_timeZone.tz(start_deposit_date?.trim(), 'Asia/Kolkata');
        const endMoment = moment_timeZone.tz(end_deposit_date?.trim(), 'Asia/Kolkata');

        const startDate = startMoment.clone().startOf('day').toDate();
        const endDate = endMoment.clone().endOf('day').toDate();

        const baseMatch = {
            insert_date: { $gte: startDate, $lte: endDate },
        };

        const basePipeline = [
            { $match: baseMatch },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "user"
                }
            },
            { $unwind: "$user" },
            {
                $project: {
                    userDB_id: "$user._id",
                    user_name: "$user.user_name",
                    mobile: "$user.mobile",
                    amount: 1,
                    tx_request_number: 1,
                    reject_remark: 1,
                    deposit_type: 1,
                    payment_method: 1,
                    txn_ref: 1,
                    fund_status: 1,
                    insert_date: 1,
                    deposit_type: 1,
                    fund_payment_receipt: 1,
                    isAction: {
                        $cond: [
                            { $ne: ['$fund_status', 0] },
                            0,
                            1
                        ]
                    }
                }
            },
        ];

        if (searchValue) {
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        { reject_remark: { $regex: `^${searchValue}`, $options: 'i' } },
                        { tx_request_number: { $regex: `^${searchValue}`, $options: 'i' } },
                        { $expr: { $regexMatch: { input: { $toString: "$amount" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$fund_status" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$payment_method" }, regex: searchRegex, options: "i" } } },
                        { $expr: { $regexMatch: { input: { $toString: "$deposit_type" }, regex: searchRegex, options: "i" } } },
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, countResult, depositAmountData, totalAcceptData, totalRejectData] = await Promise.all([
            add_funds_module.aggregate(pipelineWithPagination),
            add_funds_module.aggregate([...basePipeline, { $count: "total" }]),
            add_funds_module.aggregate([
                {
                    $match: {
                        insert_date: { $gte: startDate, $lte: endDate }
                    }
                },
                { $group: { _id: null, total: { $sum: "$amount" } } }
            ]),
            add_funds_module.aggregate([
                {
                    $match: {
                        fund_status: 1,
                        insert_date: { $gte: startDate, $lte: endDate }
                    }
                },
                { $group: { _id: null, total: { $sum: "$amount" } } }
            ]),
            add_funds_module.aggregate([
                {
                    $match: {
                        fund_status: 2,
                        insert_date: { $gte: startDate, $lte: endDate }
                    }
                },
                { $group: { _id: null, total: { $sum: "$amount" } } }
            ]),
        ]);

        const totalFiltered = countResult?.[0]?.total || 0;

        const data = results.map((v) => ({
            ...v,
            insert_date: v.insert_date
                ? moment_timeZone(v.insert_date).tz("Asia/Kolkata").format("DD MMM YYYY, hh:mm:ss A")
                : "N/A",
            receipt_url: v?.fund_payment_receipt && baseUrl
                ? `${baseUrl}/file/uploads/images/${v.fund_payment_receipt}`
                : null
        }));

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            deposit_amt: depositAmountData[0]?.total || 0,
            total_accept: totalAcceptData[0]?.total || 0,
            total_reject: totalRejectData[0]?.total || 0,
            data,
            limit
        });

    } catch (err) {
        console.error("getAutoDepositeHistory Error:", err);
        res.status(500).json({ success: false, msg: "Server error." });
    }
};

const resultHistoryListLoadData = async (req, res) => {
    try {
        let { result_dec_date } = req.body;

        // Convert input date to IST
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");

        // Get start and end of the day in IST
        const startDate = istDate.clone().startOf('day').toDate(); // 00:00:00 IST
        console.log("ðŸš€ ~ resultHistoryListLoadData ~ startDate:", startDate)
        const endDate = istDate.clone().endOf('day').toDate();     // 23:59:59.999 IST
        console.log("ðŸš€ ~ resultHistoryListLoadData ~ endDate:", endDate)

        const gamesName = await games_module.find({}, 'game_name');

        const matchStage = result_dec_date
            ? {
                result_date: { $gte: startDate, $lte: endDate },
                open_decleare_status: 1,
                close_decleare_status: 1
            }
            : {};

        const results = await game_result_history_module.aggregate([
            {
                $match: matchStage
            },
            {
                $lookup: {
                    from: 'games',
                    localField: 'gameDB_id',
                    foreignField: '_id',
                    as: 'game'
                }
            },
            {
                $unwind: {
                    path: '$game',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $project: {
                    _id: 1,
                    gameDB_id: 1,
                    result_date: 1,
                    result_date_f: {
                        $dateToString: { format: '%d %b %Y', date: '$result_date' }
                    },
                    open_decleare_date: 1,
                    close_decleare_date: 1,
                    game_name: '$game.game_name',
                    open_number: 1,
                    close_number: 1,
                    open_decleare_status: 1,
                    close_decleare_status: 1
                }
            }
        ]);

        const data = results.map((rs) => {
            const gameDB_id = rs.gameDB_id;

            // Convert result_date to Indian time zone
            const resultDateIST = moment_timeZone(rs.result_date).tz("Asia/Kolkata");

            // Open result logic
            let open_result = '';
            let open_date = rs?.open_decleare_date
                ? moment_timeZone(rs?.open_decleare_date).tz("Asia/Kolkata").format("DD MMM YYYY, hh:mm A")
                : "N/A";
            if (rs.open_number) {
                const open_num_sum = rs.open_number.split('').reduce((sum, val) => sum + parseInt(val), 0);
                const open_final_digit = open_num_sum % 10;
                open_result = `${rs.open_number}-${open_final_digit}`;
            }

            // Close result logic
            let close_result = '';
            let close_date = rs?.close_decleare_date
                ? moment_timeZone(rs?.close_decleare_date).tz("Asia/Kolkata").format("DD MMM YYYY, hh:mm A")
                : "N/A";
            if (rs.close_number) {
                const close_num_sum = rs.close_number.split('').reduce((sum, val) => sum + parseInt(val), 0);
                const close_final_digit = close_num_sum % 10;
                close_result = `${rs.close_number}-${close_final_digit}`;
            }

            // âœ… Format result_date in IST
            const result_date_long = rs?.result_date
                ? moment_timeZone(rs.result_date).tz("Asia/Kolkata").format("YYYY-MM-DDTHH:mm:ss.SSSZ") // or any other format
                : '';

            return {
                game_name: rs?.game_name || 'N/A',
                _id: rs?._id,
                result_date: resultDateIST.format("DD MMM YYYY") || 'N/A',
                result_date_long,
                open_result,
                open_date,
                close_result,
                close_date,
                gameDB_id
            };
        });

        return res.json({ data, gamesName, success: true });
    } catch (err) {
        console.error('Error loading result history:', err);
        res.status(500).json({ error: 'Internal server error' });
    }
};


// get decleared game result
// const getDecleareGameData = async (req, res) => {
//     try {
//         const gameDB_id = req.body.gameDB_id?.trim();
//         const result_dec_date = req.body.result_dec_date?.trim();
//         const session = req.body.session?.trim();

//         if (!gameDB_id || !result_dec_date || !session) {
//             return res.status(400).json({ success: false, message: 'Missing gameDB_id, result_dec_date, or session' });
//         }

//         // Convert date to IST timezone
//         const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
//         const startDate = istDate.clone().startOf('day').toDate();
//         const endDate = istDate.clone().endOf('day').toDate();

//         let matchQuery = {
//             gameDB_id,
//             result_date: { $gte: startDate, $lte: endDate },
//         };

//         if (session === 'Open') {
//             matchQuery.open_number = { $exists: true };
//         }
//         else if (session === 'Close') {
//             matchQuery.close_number = { $exists: true };
//         }
//         else {
//             return res.status(400).json({ success: false, message: 'Invalid session value' });
//         }

//         const result = await game_result_history_module.findOne(matchQuery);

//         const sumDigits_with_reminder = (str) =>
//             (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

//         let data = {
//             success: true,
//             is_open_declare: result?.open_decleare_status === 1,
//             is_close_declare: result?.close_decleare_status === 1,
//         };

//         if (session === 'Open') {
//             data.open_number = result?.open_number || '';
//             data.auto_digit = result?.open_number
//                 ? String(sumDigits_with_reminder(result.open_number))
//                 : '';
//         } else if (session === 'Close') {
//             data.close_number = result?.close_number || '';
//             data.auto_digit = result?.close_number
//                 ? String(sumDigits_with_reminder(result.close_number))
//                 : '';
//         }

//         res.json(data);
//     } catch (error) {
//         console.error('Error in getDecleareGameData:', error);
//         res.status(500).json({ success: false, message: 'Internal server error' });
//     }
// };

// get decleared game result
const getDecleareGameData = async (req, res) => {
    try {
        const gameDB_id = req.body.gameDB_id?.trim();
        const result_dec_date = req.body.result_dec_date?.trim();
        const session = req.body.session?.trim();

        if (!gameDB_id || !result_dec_date || !session) {
            return res.status(400).json({ success: false, message: 'Missing gameDB_id, result_dec_date, or session' });
        }

        // Convert date to IST timezone
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf('day').toDate();
        const endDate = istDate.clone().endOf('day').toDate();

        let matchQuery = {
            gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            result_date: { $gte: startDate, $lte: endDate },
        };

        const result = await game_result_history_module.findOne(matchQuery);
        console.log("result", result)

        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        let data = {
            success: true,
            is_open_declare: result?.open_decleare_status === 1,
            is_close_declare: result?.close_decleare_status === 1,
        };

        if (session === 'Open') {
            data.open_number = result?.open_number || '';
            data.close_number = result?.close_number || '';
            data.auto_digit = result?.open_number
                ? String(sumDigits_with_reminder(result.open_number))
                : '';
            data.selected_pana = result?.open_number || '';
        } else if (session === 'Close') {
            data.open_number = result?.open_number || '';
            data.close_number = result?.close_number || '';
            data.auto_digit = result?.close_number
                ? String(sumDigits_with_reminder(result.close_number))
                : '';
            data.selected_pana = result?.close_number || '';
        }

        // If no result found, return empty values
        if (!result) {
            data.open_number = '';
            data.close_number = '';
            data.auto_digit = '';
            data.selected_pana = '';
            data.is_open_declare = false;
            data.is_close_declare = false;
        }

        res.json(data);
    } catch (error) {
        console.error('Error in getDecleareGameData:', error);
        res.status(500).json({ success: false, message: 'Internal server error' });
    }
};

const saveOpenData = async (req, res) => {
    try {
        const {
            pana_number = "000",
            gameDB_id = "",
            result_dec_date = "",
            session = "",
            auto_digit = "0"
        } = req.body;

        // Check for required fields
        if (!gameDB_id || !result_dec_date || !session) {
            return res.status(400).json({ status: 'fail', msg: 'Missing required fields' });
        }

        // Convert to IST
        const istMoment = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istMoment.clone().startOf('day').toDate();
        const endDate = istMoment.clone().endOf('day').toDate();

        // Prepare insert and query objects
        const insertData = {
            gameDB_id,
            result_date: istMoment
        };

        const where = {
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate }
        };

        if (session === 'Open') {
            insertData.open_number = pana_number;
        } else {
            insertData.close_number = pana_number;
        }

        // Check if result already exists
        let existing = await game_result_history_module.findOne(where).populate('gameDB_id');

        if (existing) {
            if (session === 'Open') {
                existing.open_number = pana_number;
            } else {
                existing.close_number = pana_number;
            }
            await existing.save();
            return res.json({ success: true });
        }

        // Create new record
        await game_result_history_module.create(insertData);

        return res.json({ success: true });
    } catch (error) {
        console.error('Error in saveOpenData:', error);
        return res.status(500).json({ status: 'fail', msg: 'Internal server error' });
    }
};

// const saveOpenData = async (req, res) => {
//     try {
//         const {
//             open_number = "",
//             gameDB_id = "",
//             result_dec_date = "",
//             session = "",
//             auto_digit = ""
//         } = req.body;

//         if (!open_number || !gameDB_id || !result_dec_date || !session || !auto_digit) {
//             return res.status(400).json({ status: 'fail', msg: 'Missing required fields' });
//         }

//         const where = { gameDB_id, result_date: result_dec_date };

//         const existingResults = await game_result_history_module.findOne(where);

//         let open_decleare_status = 0;
//         if (existingResults) {
//             open_decleare_status = existingResults.open_decleare_status || 0;
//         }

//         let data = {};

//         if (open_decleare_status === 1) {
//             data.success = true;
//             data.msg = 'Result already declared.';
//         } else {
//             if (existingResults.length < 1) {
//                 // Insert new document
//                 const newResult = new game_result_history_module({
//                     open_number,
//                     gameDB_id: game_id,
//                     result_date: result_dec_date
//                 });
//                 await newResult.save();

//                 data.success = 'true';
//                 data.msg = 'Successfully inserted.';
//             } else {
//                 // Update existing document(s)
//                 await game_result_history_module.updateMany(where, {
//                     $set: {
//                         open_number,
//                         game_id,
//                         result_date: result_dec_date
//                     }
//                 });

//                 data.success = 'true';
//                 data.msg = 'Successfully updated.';
//             }

//             // Calculate open_result
//             if (open_number.length === 3) {
//                 const open_num =
//                     Number(open_number[0]) + Number(open_number[1]) + Number(open_number[2]);

//                 data.open_result = open_num < 10 ? open_num : open_num % 10;
//             }
//         }

//         return res.json(data);
//     } catch (error) {
//         console.error('Error in saveOpenData:', error);
//         return res.status(500).json({ status: 'fail', msg: 'Internal server error' });
//     }
// };

const decleareOpenData_Result = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { result_dec_date, gameDB_id } = req.body;

        const istDate = moment_timeZone.tz(result_dec_date, 'Asia/Kolkata');
        const startDate = istDate.clone().startOf('day').toDate();
        console.log("ðŸš€ ~ decleareOpenData_Result ~ startDate:", startDate)
        const endDate = istDate.clone().endOf('day').toDate();
        console.log("ðŸš€ ~ decleareOpenData_Result ~ endDate:", endDate)

        const result = await game_result_history_module.findOne({
            gameDB_id,
            open_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }).session(session);
        console.log("ðŸš€ ~ decleareOpenData_Result ~ result:", result)

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Please save game result first" });
        }

        if (result.open_decleare_status === 1) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Result already declared" });
        }

        const open_number = result.open_number;
        const win_digit = open_number.split('').reduce((sum, num) => sum + parseInt(num), 0) % 10;

        const game_rates = await game_rates_module.findOne({}).lean().session(session);
        const {
            single_digit_val_2, single_pana_val_2,
            double_pana_val_2, tripple_pana_val_2,
            single_digit_val_1, single_pana_val_1,
            double_pana_val_1, tripple_pana_val_1,
        } = game_rates;

        const open_result_token = uniqRandom(15);

        const result_bid = await bid_history_module.aggregate([
            {
                $match: {
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                    bid_date: { $gte: startDate, $lte: endDate },
                    session: { $ne: "Close" }
                }
            },
            { $lookup: { from: "games", localField: "gameDB_id", foreignField: "_id", as: "game" } },
            { $lookup: { from: "users", localField: "userDB_id", foreignField: "_id", as: "user" } },
            { $unwind: "$game" },
            { $unwind: "$user" },
            {
                $project: {
                    game_name: "$game.game_name",
                    userDB_id: "$user._id",
                    user_name: "$user.user_name",
                    pana: 1, session: 1, digits: 1, closedigits: 1,
                    points: 1, bid_id: "$_id", bid_tx_id: 1, pay_status: 1
                }
            }
        ]).session(session);

        for (const bid of result_bid) {
            const { pana, digits, session: bidSession, points, bid_tx_id, userDB_id, game_name, bid_id } = bid;
            let win_amt = 0;
            let matched = false;

            switch (pana) {
                case 'Single Digit':
                    if (win_digit == digits) {
                        win_amt = (single_digit_val_2 / single_digit_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Triple Pana':
                    if (open_number === digits) {
                        win_amt = (tripple_pana_val_2 / tripple_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Double Pana':
                    if (open_number === digits) {
                        win_amt = (double_pana_val_2 / double_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Single Pana':
                    if (open_number === digits) {
                        win_amt = (single_pana_val_2 / single_pana_val_1) * points;
                        matched = true;
                    }
                    break;
            }

            if (matched) {
                const tx_token = getUserRandomToken();
                const msg = `${game_name} in ${pana} (Session- ${bidSession || 'N/A'}) for bid amount- ${points} Won`;

                // âœ… Step 1: Get user wallet before increment
                const userData = await user_module.findById(userDB_id, { wallet_balance: 1 }).session(session);
                const before_wallet = userData.wallet_balance;


                await Promise.all([
                    user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: win_amt } },
                        { new: true, session }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        amount: win_amt,
                        transaction_type: 1,
                        amount_status: 8,
                        transaction_note: msg,
                        tx_request_number: tx_token,
                        bid_tx_id,
                        open_result_token,
                        before_wallet
                    }).save({ session }),
                    bid_history_module.updateOne(
                        { _id: bid_id },
                        { $set: { pay_status: 1, open_result_token } },
                        { session }
                    ),
                    new user_notification_module({
                        userDB_id,
                        msg: `Congratulations, You Won in ${game_name} for Bid Number- ${bid_tx_id}`,
                    }).save({ session })
                ]);
            } else {
                await bid_history_module.updateOne(
                    { _id: bid_id },
                    { $set: { pay_status: 2, open_result_token } },
                    { session }
                );
            }
        }

        await game_result_history_module.updateOne({
            gameDB_id,
            open_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }, {
            $set: {
                open_decleare_status: 1,
                open_decleare_date: new Date(),
                open_result_token
            }
        }, { session });

        // Notify all users with notification_status = 1
        const usersToNotify = await user_module.find({ notification_status: 1 }).lean().session(session);
        const notifications = usersToNotify.map(user => ({
            userDB_id: user._id,
            msg: `${open_number}-${win_digit}`,
        }));

        if (notifications.length > 0) {
            await user_notification_module.insertMany(notifications, { session });
        }

        await session.commitTransaction();
        session.endSession();

        return res.status(200).json({
            success: true,
            message: "Open result declared successfully",
            is_open_declare: true
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.error("Error in declaring open result:", error);
        return res.status(500).json({ success: false, message: "Server error" });
    }
};

const decleareCloseData = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { result_dec_date, gameDB_id } = req.body;

        const istDate = moment_timeZone.tz(result_dec_date, 'Asia/Kolkata');
        const startDate = istDate.clone().startOf('day').toDate();
        const endDate = istDate.clone().endOf('day').toDate();

        const result = await game_result_history_module.findOne({
            gameDB_id,
            close_number: { $ne: '0' },
            open_decleare_status: 1,
            result_date: { $gte: startDate, $lte: endDate }
        }).session(session);

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(200).json({ success: false, msg: "Please Declare Open result first" });
        }

        if (result.close_decleare_status === 1) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, msg: "Result already declared" });
        }

        const open_number = result.open_number;
        const close_number = result.close_number;

        const win_open_digit = open_number.split('').reduce((a, b) => a + Number(b), 0) % 10;
        const win_close_digit = close_number.split('').reduce((a, b) => a + Number(b), 0) % 10;

        const game_rates = await game_rates_module.findOne({}).lean().session(session);
        const {
            single_digit_val_2, jodi_digit_val_2, single_pana_val_2,
            double_pana_val_2, tripple_pana_val_2, half_sangam_val_2, full_sangam_val_2,
            group_jodi_val_2,
            red_bracket_val_2,
            single_digit_val_1, jodi_digit_val_1, single_pana_val_1,
            double_pana_val_1, tripple_pana_val_1, half_sangam_val_1, full_sangam_val_1,
            group_jodi_val_1,
            red_bracket_val_1,
        } = game_rates;

        const close_result_token = uniqRandom(15);

        const result_bid = await bid_history_module.aggregate([
            {
                $match: {
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                    bid_date: { $gte: startDate, $lte: endDate },
                    session: { $ne: "Open" }
                }
            },
            { $lookup: { from: "games", localField: "gameDB_id", foreignField: "_id", as: "game" } },
            { $lookup: { from: "users", localField: "userDB_id", foreignField: "_id", as: "user" } },
            { $unwind: "$game" },
            { $unwind: "$user" },
            {
                $project: {
                    game_name: "$game.game_name",
                    userDB_id: "$user._id",
                    user_name: "$user.user_name",
                    pana: 1, session: 1, digits: 1, closedigits: 1,
                    points: 1, bid_id: "$_id", bid_tx_id: 1, pay_status: 1
                }
            }
        ]).session(session);

        for (const bid of result_bid) {
            const {
                pana, digits, closedigits,
                session: bidSession, points, bid_tx_id,
                userDB_id, game_name, bid_id
            } = bid;

            let win_amt = 0;
            let matched = false;

            switch (pana) {
                case 'Single Digit':
                    if (win_close_digit == digits) {
                        win_amt = (single_digit_val_2 / single_digit_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Triple Pana':
                    if (close_number === digits) {
                        win_amt = (tripple_pana_val_2 / tripple_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Double Pana':
                    if (close_number === digits) {
                        win_amt = (double_pana_val_2 / double_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Single Pana':
                    if (close_number === digits) {
                        win_amt = (single_pana_val_2 / single_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Half Sangam':
                    if (open_number == digits && win_close_digit === closedigits) {
                        win_amt = (half_sangam_val_2 / half_sangam_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Full Sangam':
                    if (open_number === digits && close_number === closedigits) {
                        win_amt = (full_sangam_val_2 / full_sangam_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Jodi Digit':
                    const jodiSum1 = `${win_open_digit}${win_close_digit}`;
                    if (jodiSum1 === digits) {
                        win_amt = (jodi_digit_val_2 / jodi_digit_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Red Bracket':
                    const red_bracket_sum = `${win_open_digit}${win_close_digit}`;
                    if (red_bracket_sum === digits) {
                        win_amt = (red_bracket_val_2 / red_bracket_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Group Jodi':
                    const group_jodi = `${win_open_digit}${win_close_digit}`;
                    if (group_jodi === digits) {
                        win_amt = (group_jodi_val_2 / group_jodi_val_1) * points;
                        matched = true;
                    }
                    break;
            }

            if (matched) {
                const tx_token = getUserRandomToken();
                const note = `${game_name} in ${pana} (Session- ${bidSession || 'N/A'}) for bid amount- ${points} Won`;


                // âœ… Step 1: Get user wallet before increment
                const userData = await user_module.findById(userDB_id, { wallet_balance: 1 }).session(session);
                const before_wallet = userData.wallet_balance;

                await Promise.all([
                    user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: win_amt } },
                        { new: true, session }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        amount: win_amt,
                        transaction_type: 1,
                        amount_status: 8,
                        transaction_note: note,
                        tx_request_number: tx_token,
                        bid_tx_id,
                        close_result_token,
                        before_wallet // âœ… store old balance
                    }).save({ session }),
                    bid_history_module.updateOne(
                        { _id: bid_id },
                        { $set: { pay_status: 1, close_result_token } },
                        { session }
                    ),
                    new user_notification_module({
                        userDB_id,
                        msg: `Congratulations, You Won in ${game_name} for Bid Number- ${bid_tx_id}`,
                    }).save({ session })
                ]);
            } else {
                await bid_history_module.updateOne(
                    { _id: bid_id },
                    { $set: { pay_status: 2, close_result_token } },
                    { session }
                );
            }
        }

        await game_result_history_module.updateOne({
            gameDB_id,
            close_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }, {
            $set: {
                close_decleare_status: 1,
                close_decleare_date: new Date(),
                close_result_token
            }
        }, { session });

        const notifyUsers = await user_module.find({ notification_status: 1 }).lean().session(session);

        const closeNotifyContent = `${open_number}-${win_open_digit}${win_close_digit}-${close_number}`;
        const notifications = notifyUsers.map(user => ({
            userDB_id: user._id,
            msg: closeNotifyContent,
        }));

        if (notifications.length > 0) {
            await user_notification_module.insertMany(notifications, { session });
        }

        await session.commitTransaction();
        session.endSession();
        return res.status(200).json({
            success: true,
            message: "Close result declared successfully",
            is_close_declare: true
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.error("Error in declaring close result:", error);
        return res.status(500).json({ success: false, message: "Server error" });
    }
};

// show expected winner list according to the saved value
const getOpenWinnerList = async (req, res) => {
    try {
        const { gameDB_id, result_dec_date } = req.body;

        // Convert result date to IST
        const istMoment = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istMoment.clone().startOf("day").toDate();
        console.log("startDate", startDate)
        const endDate = istMoment.clone().endOf("day").toDate();
        console.log("endDate", endDate)

        const result = await game_result_history_module.find({
            open_number: { $ne: '0' },
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate }
        }).lean();

        console.log("result", result)

        if (!result || result.length === 0) {
            return res.status(400).json({ success: false, msg: "Please save game result first" });
        }

        const game_rate = await game_rates_module.findOne().lean();

        const allResults = [];

        for (const item of result) {
            const open_number = item.open_number;

            const {
                single_digit_val_2,
                single_pana_val_2,
                double_pana_val_2,
                tripple_pana_val_2,
                single_digit_val_1,
                single_pana_val_1,
                double_pana_val_1,
                tripple_pana_val_1
            } = game_rate;

            const bid_data = await bid_history_module.aggregate([
                {
                    $match: {
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0,
                        bid_date: { $gte: startDate, $lte: endDate },
                        session: { $ne: "Close" }
                    }
                },
                {
                    $lookup: {
                        from: "games",
                        localField: "gameDB_id",
                        foreignField: "_id",
                        as: "game"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "userDB_id",
                        foreignField: "_id",
                        as: "user"
                    }
                },
                { $unwind: { path: "$game", preserveNullAndEmptyArrays: true } },
                { $unwind: { path: "$user", preserveNullAndEmptyArrays: true } },
                {
                    $project: {
                        game_name: "$game.game_name",
                        userDB_id: "$user._id",
                        user_name: "$user.user_name",
                        pana: 1,
                        session: 1,
                        digits: 1,
                        closedigits: 1,
                        points: 1,
                        bid_id: "$_id",
                        bid_tx_id: 1,
                        pay_status: 1,
                        open_result_token: 1
                    }
                }
            ]);
            console.log("bid_data", bid_data)

            const data_array = [];
            let win_amt_sum = 0;
            let points_amt_sum = 0;

            for (const item of bid_data) {
                let win_amount = 0;
                let points = 0;

                if (item.pana === "Single Digit") {
                    let win_number = open_number.split("").reduce((acc, val) => acc + Number(val), 0) % 10;
                    if (win_number == item.digits) {
                        win_amount = (single_digit_val_2 / single_digit_val_1) * item.points;
                        points = item.points;
                    }
                } else if (item.pana === "Triple Pana" && open_number === item.digits) {
                    win_amount = (tripple_pana_val_2 / tripple_pana_val_1) * item.points;
                    points = item.points;
                } else if (item.pana === "Double Pana" && open_number === item.digits) {


                    win_amount = (double_pana_val_2 / double_pana_val_1) * item.points;

                    points = item.points;

                } else if (item.pana === "Single Pana" && open_number === item.digits) {

                    console.log("pana matched with single pana");

                    win_amount = (single_pana_val_2 / single_pana_val_1) * item.points;

                    points = item.points;

                }

                if (win_amount > 0) {
                    data_array.push({
                        points: item.points,
                        userDB_id: item.userDB_id,
                        user_name: item.user_name,
                        pana: item.pana,
                        bid_tx_id: item.bid_tx_id,
                        win_amt: win_amount
                    });

                    win_amt_sum += win_amount;
                    points_amt_sum += points;
                }
            }

            console.log("data_array", data_array)



            allResults.push({
                data: data_array,
                point: points_amt_sum,
                win_amt: win_amt_sum
            });
        }

        const flatData = allResults.flatMap(d => d.data);
        const totalPoints = allResults.reduce((sum, d) => sum + d.point, 0);
        const totalWinAmt = allResults.reduce((sum, d) => sum + d.win_amt, 0);

        return res.status(200).json({
            success: true,
            data: flatData,
            point: totalPoints,
            win_amt: totalWinAmt
        });

    } catch (error) {
        console.error("error in getOpenWinnerList:", error);
        return res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};

const getCloseWinnerList = async (req, res) => {
    try {
        const { gameDB_id, result_dec_date } = req?.body;

        // Handle date in IST
        const istMoment = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");

        const startDate = istMoment.clone().startOf("day").toDate();
        console.log("startDate", startDate)

        const endDate = istMoment.clone().endOf("day").toDate();
        console.log("endDate", endDate)

        const result = await game_result_history_module.find({
            close_number: { $ne: '0' },
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate }
        }).lean();
        console.log("result", result)

        if (!result || result.length === 0) {
            return res.status(400).json({ success: false, msg: "Please save game result first" });
        }

        const game_rate = await game_rates_module.findOne().lean();
        const allResults = [];

        for (const item of result) {
            const open_number = item.open_number;
            const close_number = item.close_number;

            const {
                single_digit_val_2, jodi_digit_val_2,
                single_pana_val_2, double_pana_val_2, tripple_pana_val_2,
                half_sangam_val_2, full_sangam_val_2,
                group_jodi_val_2,
                red_bracket_val_2,
                single_digit_val_1, jodi_digit_val_1,
                single_pana_val_1, double_pana_val_1, tripple_pana_val_1,
                half_sangam_val_1, full_sangam_val_1,
                group_jodi_val_1,
                red_bracket_val_1,
            } = game_rate;

            const bid_data = await bid_history_module.aggregate([
                {
                    $match: {
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0,
                        bid_date: { $gte: startDate, $lte: endDate },
                        session: { $ne: "Open" }
                    }
                },
                {
                    $lookup: {
                        from: "games",
                        localField: "gameDB_id",
                        foreignField: "_id",
                        as: "game"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "userDB_id",
                        foreignField: "_id",
                        as: "user"
                    }
                },
                { $unwind: "$game" },
                { $unwind: "$user" },
                {
                    $project: {
                        userDB_id: "$user._id",
                        user_name: "$user.user_name",
                        pana: 1,
                        digits: 1,
                        closedigits: 1,
                        points: 1,
                        bid_tx_id: 1
                    }
                }
            ]);
            console.log("bid_data", bid_data)

            const data_array = [];
            let win_amt_sum = 0;
            let points_amt_sum = 0;

            for (const bid of bid_data) {
                let win_amount = 0;

                const bidPoints = bid.points;

                switch (bid.pana) {
                    case 'Single Digit':
                        const digitSum = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        if (digitSum == bid.digits)
                            win_amount = (single_digit_val_2 / single_digit_val_1) * bidPoints;
                        break;

                    case 'Half Sangam':
                        const closeDigitSum = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        if (open_number == bid.digits && closeDigitSum == bid.closedigits)
                            win_amount = (half_sangam_val_2 / half_sangam_val_1) * bidPoints;
                        break;

                    case 'Full Sangam':
                        if (open_number == bid.digits && close_number == bid.closedigits)
                            win_amount = (full_sangam_val_2 / full_sangam_val_1) * bidPoints;
                        break;

                    case 'Triple Pana':
                    case 'TP':
                        if (close_number == bid.digits)
                            win_amount = (tripple_pana_val_2 / tripple_pana_val_1) * bidPoints;
                        break;

                    case 'Double Pana':
                    case 'DP':
                        if (close_number == bid.digits)
                            win_amount = (double_pana_val_2 / double_pana_val_1) * bidPoints;
                        break;

                    case 'Single Pana':
                    case 'SP':
                        if (close_number == bid.digits)
                            win_amount = (single_pana_val_2 / single_pana_val_1) * bidPoints;
                        break;

                    case 'Jodi Digit':
                        const closeDigit_jodi = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        const openDigit_jodi = open_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        const jodi_jodi = `${openDigit_jodi}${closeDigit_jodi}`;
                        if (jodi_jodi == bid.digits)
                            win_amount = (jodi_digit_val_2 / jodi_digit_val_1) * bidPoints;
                        break;
                    case 'Red Bracket':
                        const closeDigit_rb = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        const openDigit_rb = open_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        const red_bracket = `${openDigit_rb}${closeDigit_rb}`;
                        if (red_bracket == bid.digits)
                            win_amount = (red_bracket_val_2 / red_bracket_val_1) * bidPoints;
                        break;
                    case 'Group Jodi':
                        const closeDigit_gj = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        const openDigit_gj = open_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        const group_jodi = `${openDigit_gj}${closeDigit_gj}`;
                        if (group_jodi == bid.digits)
                            win_amount = (group_jodi_val_2 / group_jodi_val_1) * bidPoints;
                        break;
                }

                if (win_amount > 0) {
                    data_array.push({
                        points: bidPoints,
                        userDB_id: bid.userDB_id,
                        user_name: bid.user_name,
                        pana: bid.pana,
                        bid_tx_id: bid.bid_tx_id,
                        win_amt: win_amount
                    });
                    win_amt_sum += win_amount;
                    points_amt_sum += bidPoints;
                }
            }

            // Handle open session "Half Sangam" entries separately
            const result_2 = await bid_history_module.aggregate([
                {
                    $match: {
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0,
                        bid_date: { $gte: startDate, $lte: endDate },
                        session: "Open",
                        pana: "Half Sangam"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "userDB_id",
                        foreignField: "_id",
                        as: "user"
                    }
                },
                { $unwind: "$user" },
                {
                    $project: {
                        userDB_id: "$user._id",
                        user_name: "$user.user_name",
                        digits: 1,
                        closedigits: 1,
                        points: 1,
                        bid_tx_id: 1
                    }
                }
            ]);

            for (const bid of result_2) {
                const openDigit = open_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                if (close_number == bid.closedigits && openDigit == bid.digits) {
                    const win_amt = (half_sangam_val_2 / 10) * bid.points;
                    data_array.push({
                        points: bid.points,
                        userDB_id: bid.userDB_id,
                        user_name: bid.user_name,
                        pana: "Half Sangam",
                        bid_tx_id: bid.bid_tx_id,
                        win_amt
                    });
                    win_amt_sum += win_amt;
                    points_amt_sum += bid.points;
                }
            }

            allResults.push({
                data: data_array,
                win_amt: win_amt_sum,
                point: points_amt_sum
            });
        }

        const flatData = allResults.flatMap(d => d.data);
        const totalPoints = allResults.reduce((sum, d) => sum + d.point, 0);
        const totalWinAmt = allResults.reduce((sum, d) => sum + d.win_amt, 0);

        return res.status(200).json({
            success: true,
            data: flatData,
            point: totalPoints,
            win_amt: totalWinAmt
        });

    } catch (error) {
        console.error("Error in getCloseWinnerList:", error);
        return res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};

const starlineGameNameListGridData = async (req, res) => {
    try {
        let fields = [
            "game_name",  // "Game Name",
            "open_time",  // "Today Open",
            "close_time",  // "Today Close",
            "status",  // "Active",
            "market_status",  // "Market Status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "game_name";
        const orderDir = req?.body?.order || -1

        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            },
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$market_status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            },
                        }
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { game_name: { $regex: regexValue, $options: 'i' } },
                    ]
                };
            }
        }

        const todayName = getWeekdayNameInIST()

        const aggregatePipeline = [
            {
                $lookup: {
                    from: 'weekday_games',
                    localField: '_id',
                    foreignField: 'gameDB_id',
                    as: 'weekdayData'
                }
            },
            {
                $addFields: {
                    weekdayData: {
                        $first: {
                            $filter: {
                                input: '$weekdayData',
                                as: 'item',
                                cond: { $eq: ['$$item.week_name', todayName?.toLocaleLowerCase()] }
                            }
                        }
                    }
                }
            },
            {
                $match: searchQuery
            },
            {
                $sort: { [orderField]: orderDir }
            },
            {
                $facet: {
                    data: [
                        { $skip: skip },
                        { $limit: limit }
                    ],
                    totalCount: [
                        { $count: 'count' }
                    ]
                }
            }
        ];

        const result = await starline_games_module.aggregate(aggregatePipeline);

        const tb_data = result[0].data || [];
        const totalData = result[0].totalCount[0]?.count || 0;


        const data = tb_data.map((rs) => {
            return {
                _id: rs._id,
                game_name: rs.game_name?.toUpperCase() || '',
                open_time: get12HoursTimeFromISO(rs?.weekdayData?.open_time) || '',
                close_time: get12HoursTimeFromISO(rs?.weekdayData?.close_time) || '',
                status: rs.status,
                gameDB_id: rs._id,
                market_status: rs.weekdayData?.weekday_status || 0,
            };
        });

        const json_data = {
            success: true,
            recordsFiltered: totalData,
            data,
            limit
        };
        res.json(json_data);
    } catch (err) {
        console.error('Error in gameNameListGridData:', err);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
}

const addUpdateStarlineGame = async (req, res) => {
    try {
        let {
            game_name = "",
            open_time = "",
            gameDB_id
        } = req.body || {};

        // Trim and validate input
        game_name = toStr(game_name)
        open_time = toStr(open_time)
        gameDB_id = toStr(gameDB_id)

        if (!game_name || !open_time) {
            return res.status(400).json({ success: false, msg: "All fields are required." });
        }

        if (gameDB_id && !mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        // Convert time to IST timezone using a dummy date
        const todayStr = moment_timeZone().tz('Asia/Kolkata').format('YYYY-MM-DD');

        const openTimeIST = moment_timeZone.tz(`${todayStr} ${open_time}`, 'YYYY-MM-DD HH:mm', 'Asia/Kolkata').toDate();

        const gameData = {
            game_name: game_name.toUpperCase(),
            open_time_sort: openTimeIST,
            status: 1,
        };

        const weekDays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

        // Create or update game
        if (!gameDB_id) {
            const newGame = await starline_games_module.create(gameData);
            const weekEntries = weekDays.map((day) => ({
                gameDB_id: newGame._id,
                name: game_name.toUpperCase(),
                week_name: day.toLowerCase(),
                open_time: openTimeIST,
                open_time_sort: openTimeIST,
                weekday_status: 1
            }));

            await weekday_games_module.insertMany(weekEntries);

            return res.status(200).json({
                success: true,
                msg: "Game added successfully.",
                _id: newGame._id,
                open_time: get12HoursTimeFromISO(openTimeIST),
            });
        } else {
            for (let i = 0; i < weekDays.length; i++) {
                if (getWeekdayNameInIST()?.toUpperCase() === weekDays[i]?.toUpperCase()) {
                    await weekday_games_module.updateOne(
                        { gameDB_id, week_name: weekDays[i].toLowerCase() },
                        {
                            $set: {
                                name: game_name.toUpperCase(),
                                open_time: openTimeIST,
                                open_time_sort: openTimeIST,
                            }
                        }
                    );
                } else {
                    await weekday_games_module.updateOne(
                        { gameDB_id, week_name: weekDays[i].toLowerCase() },
                        { $set: { name: game_name.toUpperCase() } }
                    );
                }
            }

            await starline_games_module.updateOne({ _id: gameDB_id }, gameData);
            return res.status(200).json({
                success: true,
                msg: "Game updated successfully.",
                _id: gameDB_id,
                open_time: get12HoursTimeFromISO(openTimeIST),
            });
        }
    } catch (err) {
        console.error("Error in addUpdateGame:", err);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong."
        });
    }
}

const deleteStarlineGameName = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        let gameDB_id = toStr(req?.body?.gameDB_id || '');

        if (!gameDB_id) {
            return res.status(400).json({
                success: false,
                msg: "gameDB_id is required."
            });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id."
            });
        }

        const istNow = moment_timeZone().tz('Asia/Kolkata');
        const startDate = istNow.clone().startOf('day').toDate();
        const endDate = istNow.clone().endOf('day').toDate();

        const allBidsData = await starline_bid_history_module.find({ gameDB_id }).session(session);

        const isResultDeclared = await starline_game_result_history_module.findOne({
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate },
            open_decleare_status: 1
        }).session(session);

        // Refund only if result is not declared
        if (!isResultDeclared && allBidsData.length > 0) {
            for (const bid of allBidsData) {
                const user = await user_module.findById(bid.userDB_id).session(session);
                if (user) {
                    user.wallet_balance += bid.points;
                    await user.save({ session });

                    const historyData = {
                        userDB_id: user._id,
                        amount: bid.points,
                        transaction_type: 1,
                        transaction_note: `Refund for deleted starline game: ${bid.game_name}`,
                        amount_status: 7,
                        tx_request_number: getUserRandomToken(10),
                    };

                    bid.pay_status = 3;

                    await wallet_trans_history_module.create([historyData], { session });
                    await bid.save({ session });
                }
            }
        }

        await starline_games_module.findByIdAndDelete(gameDB_id, { session });
        await weekday_games_module.deleteMany({ gameDB_id }, { session });
        await starline_game_result_history_module.deleteMany({ gameDB_id }, { session });

        await session.commitTransaction();
        session.endSession();

        return res.json({
            success: true,
            msg: "Starline game and related data deleted successfully."
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();

        console.error('Error deleteStarlineGameName:', error);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong.",
            error: error.message
        });
    }
};

const getStarlineGameRates = async (req, res) => {
    try {
        let gameRates = await starline_game_rates_module.findOne()

        return res.json({
            success: true,
            msg: "Game Rates successfull sended.",
            game_rates: gameRates
        });
    } catch (error) {
        console.error("Error in getStarlineGameRates:", error);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
};

const addStarelineGameRates = async (req, res) => {
    try {
        const {
            single_digit_val_1,
            single_digit_val_2,
            single_pana_val_1,
            single_pana_val_2,
            double_pana_val_1,
            double_pana_val_2,
            tripple_pana_val_1,
            tripple_pana_val_2,
        } = req.body;

        const fields = [
            single_digit_val_1,
            single_digit_val_2,
            single_pana_val_1,
            single_pana_val_2,
            double_pana_val_1,
            double_pana_val_2,
            tripple_pana_val_1,
            tripple_pana_val_2,
        ];

        const hasAtLeastOneValue = fields.some(value => value !== undefined && value !== null && value !== '');

        if (!hasAtLeastOneValue) {
            return res.status(400).json({ success: false, msg: "At least one field is required." });
        }

        const gamesRatesData = {
            single_digit_val_1,
            single_digit_val_2,
            single_pana_val_1,
            single_pana_val_2,
            double_pana_val_1,
            double_pana_val_2,
            tripple_pana_val_1,
            tripple_pana_val_2,
        };

        let gameRates = await starline_game_rates_module.findOne()

        if (!gameRates) {
            await starline_game_rates_module.create(gamesRatesData);
            return res.json({
                success: true,
                msg: "Game Rates Successfully Added.",
            });
        } else {
            await starline_game_rates_module.updateOne({}, gamesRatesData);
            return res.json({
                success: true,
                msg: "Game Rates Successfully Updated.",
            });
        }
    } catch (error) {
        console.error("Error in addStarelineGameRates:", error);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
}

const getStarlineGameList = async (req, res) => {
    try {
        const gamesName = await starline_games_module.find({}, 'game_name');
        return res.json({ success: true, gamesName });
    } catch (err) {
        console.error('Error in getStarlineGameList:', err);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getStarlineBidHistoryData = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            predictionDate,
            gameDB_id,
            gameType = ""
        } = req.body;

        const fields = [
            "user_name",
            "bid_tx_id",
            "game_name",
            "pana",
            "digits",
            "digits",
            "points",
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const matchFilter = {
            gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            pay_status: 0,
            bid_date: { $gte: startDate, $lte: endDate },
        };

        if (gameType !== 'all') {
            matchFilter.pana = gameType
        }

        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    points: 1,
                    pana: 1,
                    game_name: 1,
                    bid_tx_id: 1,
                    digits: 1,
                    user_name: "$userData.user_name"
                }
            },
        ];

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        { game_name: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$digits" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            starline_bid_history_module.aggregate(pipelineWithPagination),
            starline_bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        const data = results.map((v) => {
            const common = {
                _id: v._id,
                points: v.points,
                game_type: v.pana,
                game_name: v.game_name,
                bid_tx_id: v.bid_tx_id,
                user_name: v.user_name,
            };

            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...common,
                        pana: 'N/A',
                        digit: v.digits,
                    };

                default:
                    return {
                        ...common,
                        pana: v.digits,
                        digit: sumDigits_with_reminder(String(v.digits)),
                    };
            }
        });

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("getBidHistoryData Error:", err);
        return res.status(500).json({ success: false, msg: "Server error: " + err.message });
    }
};

const getStarlineSellReport = async (req, res) => {
    try {
        const { gameDB_id, predictionDate, gameType = "all", session } = req.body;

        if (!gameDB_id) {
            return res.status(400).json({ success: false, msg: "Missing gameDB_id." });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        let baseFilter = {
            gameDB_id,
            bid_date: { $gte: startDate, $lte: endDate }
        };

        if (gameType !== "all") {
            baseFilter.pana = gameType;
        }

        const results = await starline_bid_history_module.find(baseFilter);

        const data = {
            single_digit: [],
            single_pana: [],
            double_pana: [],
            triple_pana: [],
        };

        // Helper to aggregate points
        const aggregatePoints = (category, digit, points) => {
            const existing = data[category].find((item) => item.digit === digit);
            if (existing) {
                existing.points += points;
            } else {
                data[category].push({ digit, points });
            }
        };

        results.forEach((v) => {
            const digit = v.digits;
            const points = Number(v.points) || 0;

            switch (v.pana) {
                case "Single Digit":
                    aggregatePoints("single_digit", digit, points);
                    break;
                case "Single Pana":
                    aggregatePoints("single_pana", digit, points);
                    break;
                case "Double Pana":
                    aggregatePoints("double_pana", digit, points);
                    break;
                case "Triple Pana":
                    aggregatePoints("triple_pana", digit, points);
                    break;
            }
        });

        return res.json({
            success: true,
            data
        });

    } catch (err) {
        console.error("getStarlineSellReport Error:", err);
        return res.status(500).json({ success: false, msg: "Server error. Please try again later." });
    }
};

const getStarlineWinnerList = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            predictionDate,
            gameDB_id,
            selected_number = "",
        } = req.body;

        const fields = [
            "user_name",
            "points",
            "winning_points",
            "pana",
            "bid_tx_id"
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const matchFilter = {
            gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            pay_status: 0,
            bid_date: { $gte: startDate, $lte: endDate },
        };

        const sumDigits = (str) =>
            str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0);

        const selected_number_sum = sumDigits(selected_number);
        const selected_number_int = parseInt(selected_number, 10);

        // Add digit-based match logic to aggregation pipeline
        const matchDigitLogic = {
            $match: {
                $expr: {
                    $switch: {
                        branches: [
                            {
                                case: { $eq: ["$pana", "Single Digit"] },
                                then:
                                    { $eq: [{ $toInt: "$digits" }, selected_number_sum] }
                            },
                            {
                                case: {
                                    $in: [
                                        "$pana",
                                        ["Single Pana", "Double Pana", "Triple Pana"]
                                    ]
                                },
                                then: {
                                    $eq: [{ $toInt: "$digits" }, selected_number_int]
                                }
                            }
                        ],
                        default: false
                    }
                }
            }
        };

        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            {
                $lookup: {
                    from: "starline_games",
                    localField: "gameDB_id",
                    foreignField: "_id",
                    as: "gameData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    points: 1,
                    winning_points: 1,
                    pana: 1,
                    bid_tx_id: 1,
                    pay_status: 1,
                    digits: 1,
                    user_name: "$userData.user_name"
                }
            },
            matchDigitLogic
        ];

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$winning_points" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr, totalsArr] = await Promise.all([
            starline_bid_history_module.aggregate(pipelineWithPagination),
            starline_bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
            starline_bid_history_module.aggregate([
                ...basePipeline,
                {
                    $group: {
                        _id: null,
                        total_winning_points: { $sum: "$winning_points" },
                        total_bid_amount: { $sum: "$points" }
                    }
                }
            ])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        const total_winning_points = totalsArr[0]?.total_winning_points || 0;
        const total_bid_amount = totalsArr[0]?.total_bid_amount || 0;

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            total_winning_points,
            total_bid_amount,
            data: results,
            limit
        });

    } catch (err) {
        console.error("getStarlineWinnerList Error:", err);
        return res.status(500).json({ success: false, msg: "Server error: " + err.message });
    }
};

const starlineResultHistoryListLoadData = async (req, res) => {
    try {
        let { result_dec_date } = req.body;

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const gamesName = await starline_games_module.find({}, 'game_name');

        const matchStage = result_dec_date
            ? { result_date: { $gte: startDate, $lte: endDate } }
            : {};

        const results = await starline_game_result_history_module.aggregate([
            {
                $match: matchStage
            },
            {
                $lookup: {
                    from: 'starline_games',
                    localField: 'gameDB_id',
                    foreignField: '_id',
                    as: 'game'
                }
            },
            {
                $unwind: {
                    path: '$game'
                }
            },
            {
                $project: {
                    _id: 1,
                    gameDB_id: 1,
                    result_date: 1,
                    result_date_f: {
                        $dateToString: { format: '%d %b %Y', date: '$result_date' }
                    },
                    open_decleare_date: {
                        $cond: {
                            if: { $ifNull: ['$open_decleare_date', false] },
                            then: { $dateToString: { format: '%d %b %Y %H:%M:%S', date: '$open_decleare_date' } },
                            else: 'N/A'
                        }
                    },
                    game_name: '$game.game_name',
                    open_number: 1,
                    close_number: 1,
                    open_decleare_status: 1,
                }
            }
        ]);

        const data = results.map((rs) => {
            const gameDB_id = rs.gameDB_id;

            // Open result logic
            let open_result = '';
            let open_date = rs?.open_decleare_date || 'N/A';
            if (rs.open_number) {
                const open_num_sum = rs.open_number.split('').reduce((sum, val) => sum + parseInt(val), 0);
                const open_final_digit = open_num_sum % 10;

                open_result = `${rs.open_number}-${open_final_digit}`;
            }

            return {
                game_name: rs?.game_name || 'N/A',
                result_date: rs?.result_date_f || 'N/A',
                result_date_long: rs?.result_date || '',
                open_result,
                open_date,
                gameDB_id
            };
        });

        return res.json({ data, gamesName, success: true });
    } catch (error) {
        console.error('Error loading Starline result history:', error);
        res.status(500).json({ success: false, error: 'Server error' });
    }
};

const getDecleareStarlineGameData = async (req, res) => {
    try {
        const gameDB_id = req.body.gameDB_id?.trim();
        const result_dec_date = req.body.result_dec_date?.trim();

        if (!gameDB_id || !result_dec_date) {
            return res.status(400).json({ success: false, message: 'Missing gameDB_id or result_dec_date' });
        }

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        let matchQuery = {
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate },
            open_number: { $exists: true }
        };

        const result = await starline_game_result_history_module.findOne(matchQuery);

        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        let data = {
            success: true,
            is_open_declare: result?.open_decleare_status === 1 ? true : false,
        };

        data.open_number = result?.open_number || '';
        data.auto_digit = result?.open_number
            ? String(sumDigits_with_reminder(result.open_number))
            : '';
        res.json(data);
    } catch (error) {
        console.error('Error in getDeclareGameData:', error);
        res.status(500).json({ success: false, msg: 'Internal server error' });
    }
};

const saveOpenStarlineGameData = async (req, res) => {
    try {
        const {
            pana_number = "",
            gameDB_id = "",
            result_dec_date = "",
            auto_digit = ""
        } = req.body;

        // Check for required fields
        if (!pana_number || !gameDB_id || !result_dec_date || !auto_digit) {
            return res.status(400).json({ status: 'fail', msg: 'Missing required fields' });
        }

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        // Prepare insert and query objects
        const insertData = {
            gameDB_id,
            result_date: istDate,
            open_number: pana_number
        };

        const where = {
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate },
        };

        // Check if result already exists
        let existing = await starline_game_result_history_module.findOne(where).populate('gameDB_id');

        if (existing) {
            existing.open_number = pana_number;
            await existing.save()
            return res.json({ success: true });
        }

        // Create new record
        await starline_game_result_history_module.create(insertData);

        return res.json({ success: true });
    } catch (err) {
        console.error('Error in saveOpenData:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal server error'
        });
    }
};

const getOpenStarlineWinnerList = async (req, res) => {
    try {
        const { gameDB_id, result_dec_date } = req.body

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const result = await starline_game_result_history_module.find({
            open_number: { $ne: '0' },
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate }
        }).lean()

        if (result.length <= 0) {
            return res.status(400).json({ success: false, msg: "Please save game result first" })
        }

        const game_rate = await starline_game_rates_module.findOne().lean()
        const [data] = await Promise.all(result.map(async (item) => {
            const open_number = item.open_number

            const single_digit_val_2 = game_rate.single_digit_val_2;
            const single_pana_val_2 = game_rate.single_pana_val_2;
            const double_pana_val_2 = game_rate.double_pana_val_2;
            const tripple_pana_val_2 = game_rate.tripple_pana_val_2;
            const single_digit_val_1 = game_rate.single_digit_val_1;
            const single_pana_val_1 = game_rate.single_pana_val_1;
            const double_pana_val_1 = game_rate.double_pana_val_1;
            const tripple_pana_val_1 = game_rate.tripple_pana_val_1;

            const bid_data = await starline_bid_history_module.aggregate([
                {
                    $match: {
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0,
                        bid_date: { $gte: startDate, $lte: endDate },
                    }
                }, {
                    $lookup: {
                        from: "starline_games",
                        localField: "gameDB_id",
                        foreignField: "_id",
                        as: "game"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "userDB_id",
                        foreignField: "_id",
                        as: "user",
                    },
                },
                {
                    $unwind: {
                        path: "$game",
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $unwind: {
                        path: "$user",
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $project: {
                        game_name: "$game.game_name",
                        userDB_id: "$user._id",
                        user_name: "$user.user_name",
                        pana: 1,
                        session: 1,
                        digits: 1,
                        points: 1,
                        bid_id: "$_id",
                        bid_tx_id: 1,
                        pay_status: 1,
                        open_result_token: 1,
                    },
                },
            ])

            const data_array = []
            let win_amt_sum = 0
            let points_amt_sum = 0

            bid_data.forEach(async (item, i) => {
                let win_amount = 0
                let points = 0
                if (item.pana == "Single Digit") {
                    let win_number = open_number.toString().split("").reduce((acc, curr) => {
                        return acc + Number(curr)
                    }, 0)
                    if (win_number > 9)
                        win_number = win_number % 10;
                    if (win_number == item.digits) {
                        win_amount = (single_digit_val_2 / single_digit_val_1) * item.points;

                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                } else if (item.pana == 'Triple Pana') {
                    if (open_number == item.digits) {
                        win_amount = (tripple_pana_val_2 / tripple_pana_val_1) * item.points;

                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                } else if (item.pana == 'Double Pana') {
                    if (open_number == item.digits) {
                        win_amount = (double_pana_val_2 / double_pana_val_1) * item.points;

                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                } else if (item.pana == 'Single Pana') {
                    if (open_number == item.digits) {
                        win_amount = (single_pana_val_2 / single_pana_val_1) * item.points;

                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                }

                win_amt_sum += win_amount;
                points_amt_sum += points;
            })

            return {
                data: data_array,
                point: points_amt_sum,
                win_amt: win_amt_sum
            }
        }))
        res.status(200).json({ success: true, data: data.data, point: data.point, win_amt: data.win_amt })
    } catch (err) {
        console.error(err);
        res.status(500).json({ success: false, msg: 'Internal server error' });
    }
};

const decleareOpenStarlineData = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { result_dec_date, gameDB_id } = req.body;
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const result = await starline_game_result_history_module.findOne({
            gameDB_id: gameDB_id,
            open_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }).session(session);

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Please save game result first" });
        }

        if (result.open_decleare_status == 1) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Result already declared" });
        }

        const open_number = result.open_number;

        let win_number_not = open_number.toString().split("").reduce((acc, curr) => acc + Number(curr), 0) % 10;

        const game_rates = await game_rates_module.findOne({}).session(session);

        const {
            single_digit_val_2, single_pana_val_2,
            double_pana_val_2, tripple_pana_val_2,
            single_digit_val_1, single_pana_val_1,
            double_pana_val_1, tripple_pana_val_1,
        } = game_rates;

        const open_result_token = uniqRandom(15);

        const result_bid = await starline_bid_history_module.aggregate([
            {
                $match: {
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                    bid_date: { $gte: startDate, $lte: endDate },
                    session: { $ne: "Close" }
                }
            },
            { $lookup: { from: "starline_games", localField: "gameDB_id", foreignField: "_id", as: "game" } },
            { $lookup: { from: "users", localField: "userDB_id", foreignField: "_id", as: "user" } },
            { $unwind: "$game" },
            { $unwind: "$user" },
            {
                $project: {
                    game_name: "$game.game_name",
                    userDB_id: "$user._id",
                    user_name: "$user.user_name",
                    pana: 1, session: 1, digits: 1, closedigits: 1,
                    points: 1, bid_id: "$_id", bid_tx_id: 1, pay_status: 1
                }
            }
        ]).session(session);

        for (const item of result_bid) {
            const { pana, digits, points, bid_tx_id, userDB_id } = item;
            let win_amt = 0, matched = false;

            const winSingleDigit = open_number.toString().split('').reduce((a, b) => a + Number(b), 0) % 10;

            switch (pana) {
                case 'Single Digit':
                    if (winSingleDigit == digits) {
                        win_amt = (single_digit_val_2 / single_digit_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Triple Pana':
                    if (open_number == digits) {
                        win_amt = (tripple_pana_val_2 / tripple_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Double Pana':
                    if (open_number == digits) {
                        win_amt = (double_pana_val_2 / double_pana_val_1) * points;
                        matched = true;
                    }
                    break;
                case 'Single Pana':
                    if (open_number == digits) {
                        win_amt = (single_pana_val_2 / single_pana_val_1) * points;
                        matched = true;
                    }
                    break;
            }

            if (matched) {
                const msg = `${item.game_name} in ${pana} for bid amount- ${points} Won`;
                const tx_token = getUserRandomToken();

                await Promise.all([
                    user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: win_amt } },
                        { new: true, session }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        amount: win_amt,
                        transaction_type: 1,
                        amount_status: 8,
                        transaction_note: msg,
                        tx_request_number: tx_token,
                        bid_tx_id,
                        open_result_token
                    }).save({ session }),
                    starline_bid_history_module.updateOne(
                        { _id: item.bid_id },
                        { $set: { pay_status: 1, open_result_token } },
                        { session }
                    ),
                    new user_notification_module({
                        userDB_id,
                        msg: `Congratulations ,You Won in ${item.game_name} for Bid Number- ${bid_tx_id}`,
                    }).save({ session })
                ]);
            } else {
                await starline_bid_history_module.updateOne({ _id: item.bid_id }, { $set: { pay_status: 2 } }, { session });
            }
        }

        await starline_game_result_history_module.updateOne({
            gameDB_id,
            open_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }, {
            $set: {
                open_decleare_status: 1,
                open_decleare_date: new Date(),
                open_result_token
            }
        }, { session });

        const usersData = await user_module.find({ notification_status: 1 }).session(session);

        for (const user of usersData) {
            const notification_content = `${open_number}-${win_number_not}`;
            await new user_notification_module({ userDB_id: user._id, msg: notification_content }).save({ session });
        }

        await session.commitTransaction();
        session.endSession();
        return res.status(200).json({ success: true, message: "Open result declared successfully" });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.error("Error in declaring open result:", error);
        return res.status(500).json({ success: false, message: "Server error" });
    }
};

const starlineResultHistoryListGridData = async (req, res) => {
    try {
        const fields = [
            "gameDB_id.game_name",   // 0
            "result_date",           // 1
            "open_decleare_date",    // 2
            "open_number"            // 3
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;
        const fieldIndex = parseInt(req.body.fieldIndex) || 0;
        const orderField = fields[fieldIndex] || "result_date";
        const orderDir = req?.body?.order === 1 ? 1 : -1;

        const isNumeric = !isNaN(searchValue);
        const regexValue = `^${searchValue}`;

        const pipeline = [
            {
                $lookup: {
                    from: "starline_games",
                    localField: "gameDB_id",
                    foreignField: "_id",
                    as: "gameDB_id"
                }
            },
            {
                $unwind: {
                    path: "$gameDB_id",
                    preserveNullAndEmptyArrays: true
                }
            },
        ];

        // Search filtering
        if (searchValue) {
            if (isNumeric) {
                pipeline.push({
                    $match: {
                        $expr: {
                            $regexMatch: {
                                input: { $toString: "$open_number" },
                                regex: regexValue,
                                options: "i"
                            }
                        }
                    }
                });
            } else {
                pipeline.push({
                    $match: {
                        "gameDB_id.game_name": {
                            $regex: regexValue,
                            $options: "i"
                        }
                    }
                });
            }
        }

        // Count filtered results
        const totalFilteredAgg = await starline_game_result_history_module.aggregate([...pipeline, { $count: "total" }]);
        const totalFiltered = totalFilteredAgg[0]?.total || 0;

        // Sort, Skip, Limit
        pipeline.push({ $sort: { [orderField]: orderDir } });
        pipeline.push({ $skip: skip });
        pipeline.push({ $limit: limit });

        // Projection
        pipeline.push({
            $project: {
                _id: 1,
                result_date: 1,
                open_decleare_date: 1,
                open_number: 1,
                game_name: "$gameDB_id.game_name"
            }
        });

        // Execute
        const results = await starline_game_result_history_module.aggregate(pipeline);

        // Format
        const data = results.map((rs) => {
            const openNum = rs.open_number?.toString() || '';
            const sumMod = openNum
                ? openNum.split("").reduce((acc, digit) => acc + Number(digit), 0) % 10
                : '';

            return {
                _id: rs._id,
                game_name: rs.game_name || 'N/A',
                result_date: formatDateToDDMMYYYY(rs.result_date),
                open_decleare_date: rs?.open_decleare_date
                    ? formatDateToDDMMYYYY(rs.open_decleare_date)
                    : 'N/A',
                open_number: `${rs.open_number}-${sumMod}`
            };
        });

        res.json({
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (error) {
        console.error("Error:", error);
        res.status(500).json({ error: "Internal server error" });
    }
};

const getStarlineWinningReport = async (req, res) => {
    try {
        const gameDB_id = req?.body?.gameDB_id?.trim() || "";
        const result_dec_date = req?.body?.result_dec_date?.trim() || "";

        if (!result_dec_date || !gameDB_id) {
            return res.status(400).json({
                success: false,
                msg: 'Missing required fields.'
            });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        let data = await starline_game_result_history_module.aggregate([
            {
                $match: {
                    result_date: {
                        $gte: startDate,
                        $lte: endDate
                    }
                }
            },
            {
                $lookup: {
                    from: 'wallet_trans_histories',
                    localField: 'open_result_token',
                    foreignField: 'open_result_token',
                    as: 'wallet'
                }
            },
            {
                $unwind: {
                    path: '$wallet',
                }
            },
            {
                $lookup: {
                    from: 'starline_bid_histories',
                    localField: 'wallet.bid_tx_id',
                    foreignField: 'bid_tx_id',
                    as: 'bid'
                }
            },
            {
                $unwind: {
                    path: '$bid',
                }
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'bid.userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            {
                $unwind: {
                    path: '$user',
                }
            },
            {
                $match: {
                    'bid.gameDB_id': new mongoose.Types.ObjectId(gameDB_id)
                }
            },
            {
                $project: {
                    user_name: '$user.user_name',
                    userDB_id: '$wallet.userDB_id',
                    game_name: '$bid.game_name',
                    session: '$bid.session',
                    winning_points: '$bid.winning_points',
                    transaction_note: '$wallet.transaction_note',
                    tx_request_number: '$wallet.tx_request_number',
                    insert_date: '$wallet.insert_date',
                    pana: '$bid.pana',
                    digits: '$bid.digits',
                    closedigits: '$bid.closedigits',
                    points: '$bid.points',
                    bidDB_id: '$bid._id',
                    bid_tx_id: '$bid.bid_tx_id'
                }
            }
        ]);

        data = data.map((v) => ({
            ...v,
            digit: v?.digits?.toString().split("").reduce((acc, curr) => acc + Number(curr), 0) % 10 || ''
        }))

        res.json({ success: true, getResultHistory: data });
    } catch (err) {
        console.error(err);
        res.status(500).json({ success: false, error: 'Something went wrong.' });
    }
};

const galidisswarGameNameListGridData = async (req, res) => {
    try {
        let fields = [
            "game_name",  // "Game Name",
            "open_time",  // "Today Open",
            "close_time",  // "Today Close",
            "status",  // "Active",
            "market_status",  // "Market Status",
        ]

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 1;
        const searchValue = req.body.searchValue?.trim() || '';
        const skip = !searchValue ? (page - 1) * limit : 0;

        const fieldIndex = req.body.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "game_name";
        const orderDir = req?.body?.order || -1

        let searchQuery = {};

        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            },
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$market_status" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            },
                        }
                    ]
                };
            } else {
                searchQuery = {
                    $or: [
                        { game_name: { $regex: regexValue, $options: 'i' } },
                    ]
                };
            }
        }

        const todayName = getWeekdayNameInIST()

        const aggregatePipeline = [
            {
                $lookup: {
                    from: 'weekday_games',
                    localField: '_id',
                    foreignField: 'gameDB_id',
                    as: 'weekdayData'
                }
            },
            {
                $addFields: {
                    weekdayData: {
                        $first: {
                            $filter: {
                                input: '$weekdayData',
                                as: 'item',
                                cond: { $eq: ['$$item.week_name', todayName?.toLocaleLowerCase()] }
                            }
                        }
                    }
                }
            },
            {
                $match: searchQuery
            },
            {
                $sort: { [orderField]: orderDir }
            },
            {
                $facet: {
                    data: [
                        { $skip: skip },
                        { $limit: limit }
                    ],
                    totalCount: [
                        { $count: 'count' }
                    ]
                }
            }
        ];

        const result = await gali_disswar_games_module.aggregate(aggregatePipeline);

        const tb_data = result[0].data || [];
        const totalData = result[0].totalCount[0]?.count || 0;


        const data = tb_data.map((rs) => {
            return {
                _id: rs._id,
                game_name: rs.game_name?.toUpperCase() || '',
                open_time: get12HoursTimeFromISO(rs?.weekdayData?.open_time) || '',
                close_time: get12HoursTimeFromISO(rs?.weekdayData?.close_time) || '',
                status: rs.status,
                gameDB_id: rs._id,
                market_status: rs.weekdayData?.weekday_status || 0,
            };
        });

        const json_data = {
            success: true,
            recordsFiltered: totalData,
            data,
            limit
        };

        res.json(json_data);
    } catch (err) {
        console.error('Error in galidisswarGameNameListGridData:', err);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
}

const addUpdateGalidisswarGame = async (req, res) => {
    try {
        let {
            game_name = "",
            open_time = "",
            gameDB_id
        } = req.body || {};

        // Trim and validate input
        game_name = toStr(game_name)
        open_time = toStr(open_time)
        gameDB_id = toStr(gameDB_id)

        if (!game_name || !open_time) {
            return res.status(400).json({ success: false, msg: "All fields are required." });
        }

        if (gameDB_id && !mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        // Convert time to IST timezone using a dummy date
        const todayStr = moment_timeZone().tz('Asia/Kolkata').format('YYYY-MM-DD');

        const openTimeIST = moment_timeZone.tz(`${todayStr} ${open_time}`, 'YYYY-MM-DD HH:mm', 'Asia/Kolkata').toDate();

        const gameData = {
            game_name: game_name.toUpperCase(),
            open_time_sort: openTimeIST,
            status: 1,
        };

        const weekDays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

        // Create or update game
        if (!gameDB_id) {
            const newGame = await gali_disswar_games_module.create(gameData);
            const weekEntries = weekDays.map((day) => ({
                gameDB_id: newGame._id,
                name: game_name.toUpperCase(),
                week_name: day.toLowerCase(),
                open_time: openTimeIST,
                open_time_sort: openTimeIST,
                weekday_status: 1
            }));

            await weekday_games_module.insertMany(weekEntries);

            return res.status(200).json({
                success: true,
                msg: "Game added successfully.",
                _id: newGame._id,
                open_time: get12HoursTimeFromISO(openTimeIST),
            });
        } else {
            for (let i = 0; i < weekDays.length; i++) {
                if (getWeekdayNameInIST()?.toUpperCase() === weekDays[i]?.toUpperCase()) {
                    await weekday_games_module.updateOne(
                        { gameDB_id, week_name: weekDays[i].toLowerCase() },
                        {
                            $set: {
                                name: game_name.toUpperCase(),
                                open_time: openTimeIST,
                                open_time_sort: openTimeIST,
                            }
                        }
                    );
                } else {
                    await weekday_games_module.updateOne(
                        { gameDB_id, week_name: weekDays[i].toLowerCase() },
                        { $set: { name: game_name.toUpperCase() } }
                    );
                }
            }

            await gali_disswar_games_module.updateOne({ _id: gameDB_id }, gameData);
            return res.status(200).json({
                success: true,
                msg: "Game updated successfully.",
                _id: gameDB_id,
                open_time: get12HoursTimeFromISO(openTimeIST),
            });
        }
    } catch (err) {
        console.error("Error in addUpdateGalidisswarGame:", err);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong."
        });
    }
}

const deleteGalidisswarGameName = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        let gameDB_id = toStr(req?.body?.gameDB_id || '');

        if (!gameDB_id) {
            return res.status(400).json({
                success: false,
                msg: "gameDB_id is required."
            });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id.",
            });
        }

        const istDate = moment_timeZone().tz('Asia/Kolkata');
        const startDate = istDate.clone().startOf('day').toDate();
        const endDate = istDate.clone().endOf('day').toDate();

        const allBidsData = await gali_disswar_bid_history_module.find({ gameDB_id }).session(session);

        const isResultDeclare = await gali_disswar_game_result_history_module.findOne({
            result_date: { $gte: startDate, $lte: endDate },
            gameDB_id,
            close_decleare_status: 1
        }).session(session);

        if (!isResultDeclare && allBidsData.length > 0) {
            for (const bid of allBidsData) {
                const user = await user_module.findById(bid.userDB_id).session(session);
                if (user) {
                    user.wallet_balance += bid.points;
                    await user.save({ session });

                    const historyData = {
                        userDB_id: user._id,
                        amount: bid.points,
                        transaction_type: 1,
                        transaction_note: `Refund for deleted Jackpot game: ${bid.game_name}`,
                        amount_status: 7,
                        tx_request_number: getUserRandomToken(10),
                    };

                    bid.pay_status = 3;
                    await wallet_trans_history_module.create([historyData], { session });
                }
            }

            // Save updated bids
            await Promise.all(allBidsData.map(bid => bid.save({ session })));
        }

        // Delete game and weekday data
        await gali_disswar_games_module.findByIdAndDelete(gameDB_id, { session });
        await weekday_games_module.deleteMany({ gameDB_id }, { session });
        await gali_disswar_game_result_history_module.deleteMany({ gameDB_id }, { session });

        await session.commitTransaction();
        session.endSession();

        return res.json({
            success: true,
            msg: "Jackpot game and related data deleted successfully."
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();

        console.error('Error deleting Jackpot game:', error);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong.",
            error: error.message
        });
    }
};

const getGalidisswarGameRates = async (req, res) => {
    try {
        let gameRates = await gali_disswar_game_rates_module.findOne()

        return res.json({
            success: true,
            msg: "Game Rates successfull sended.",
            game_rates: gameRates
        });
    } catch (error) {
        console.error("Error in getStarlineGameRates:", error);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
};

const addGalidisswarGameRates = async (req, res) => {
    try {
        const {
            red_bracket_val_1,
            red_bracket_val_2,
            group_jodi_val_1,
            group_jodi_val_2,
            jodi_digit_val_1,
            jodi_digit_val_2,
        } = req.body;

        const fields = [
            red_bracket_val_1,
            red_bracket_val_2,
            group_jodi_val_1,
            group_jodi_val_2,
            jodi_digit_val_1,
            jodi_digit_val_2,
        ];

        const hasAtLeastOneValue = fields.some(value => value !== undefined && value !== null && value !== '');

        if (!hasAtLeastOneValue) {
            return res.status(400).json({ success: false, msg: "At least one field is required." });
        }

        const gamesRatesData = {
            red_bracket_val_1,
            red_bracket_val_2,
            group_jodi_val_1,
            group_jodi_val_2,
            jodi_digit_val_1,
            jodi_digit_val_2,
        };

        let gameRates = await gali_disswar_game_rates_module.findOne()

        if (!gameRates) {
            await gali_disswar_game_rates_module.create(gamesRatesData);
            return res.json({
                success: true,
                msg: "Game Rates Successfully Added.",
            });
        } else {
            await gali_disswar_game_rates_module.updateOne({}, gamesRatesData);
            return res.json({
                success: true,
                msg: "Game Rates Successfully Updated.",
            });
        }
    } catch (error) {
        console.error("Error in addGalidisswarGameRates:", error);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
}

const getGalidisswarGameList = async (req, res) => {
    try {
        const gamesName = await gali_disswar_games_module.find({}, 'game_name');
        return res.json({ success: true, gamesName });
    } catch (err) {
        console.error('Error in getStarlineGameList:', err);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getGalidisswarBidHistoryData = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            predictionDate,
            gameDB_id,
            gameType = ""
        } = req.body;

        const fields = [
            "user_name",
            "bid_tx_id",
            "game_name",
            "pana",
            "digits",
            "points",
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const matchFilter = {
            gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            pay_status: 0,
            bid_date: { $gte: startDate, $lte: endDate },
        };

        if (gameType !== 'all') {
            matchFilter.pana = gameType
        }

        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    points: 1,
                    pana: 1,
                    game_name: 1,
                    bid_tx_id: 1,
                    digits: 1,
                    user_name: "$userData.user_name"
                }
            },
        ];

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        { game_name: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$digits" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            gali_disswar_bid_history_module.aggregate(pipelineWithPagination),
            gali_disswar_bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;

        const data = results.map((v) => {
            const common = {
                _id: v._id,
                points: v.points,
                game_type: v.pana,
                game_name: v.game_name,
                bid_tx_id: v.bid_tx_id,
                user_name: v.user_name,
            };

            switch (v.pana) {
                case 'Right Digit':
                case 'Left Digit':
                    return {
                        ...common,
                        pana: 'N/A',
                        digit: v.digits,
                    };

                case 'Jodi Digit':
                case 'Red Bracket':
                case 'Group Jodi':
                    return {
                        ...common,
                        pana: v.digits,
                        digit: String(v.digits),
                    };

                default:
                    return {
                        ...common,
                        pana: 'N/A',
                        digit: 'N/A',
                    };
            }
        });

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("getBidHistoryData Error:", err);
        return res.status(500).json({ success: false, msg: "Server error: " + err.message });
    }
};

const getGalidisswarSellReport = async (req, res) => {
    try {
        const { gameDB_id, predictionDate, gameType = "all" } = req.body;

        if (!gameDB_id) {
            return res.status(400).json({ success: false, msg: "Missing gameDB_id." });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        let baseFilter = {
            gameDB_id,
            bid_date: { $gte: startDate, $lte: endDate }
        };

        if (gameType !== "all") {
            baseFilter.pana = gameType;
        }

        const results = await gali_disswar_bid_history_module.find(baseFilter);

        const data = {
            left_digit: [],
            right_digit: [],
            jodi_digit: [],
            group_jodi: [],
            red_bracket: [],
        };

        // Helper to aggregate points
        const aggregatePoints = (category, digit, points) => {
            const existing = data[category].find((item) => item.digit === digit);
            if (existing) {
                existing.points += points;
            } else {
                data[category].push({ digit, points });
            }
        };

        results.forEach((v) => {
            const digit = v.digits;
            const points = Number(v.points) || 0;

            switch (v.pana) {
                case "Left Digit":
                    aggregatePoints("left_digit", digit, points);
                    break;
                case "Right Digit":
                    aggregatePoints("right_digit", digit, points);
                    break;
                case 'Group Jodi':
                case 'Red Bracket':
                case "Jodi Digit":
                    aggregatePoints("jodi_digit", digit, points);
                    break;
            }
        });

        return res.json({
            success: true,
            data
        });

    } catch (err) {
        console.error("getGalidisswarSellReport Error:", err);
        return res.status(500).json({ success: false, msg: "Server error. Please try again later." });
    }
};

const getGalidisswarWinnerList = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            predictionDate,
            gameDB_id,
            selected_number = "",
        } = req.body;

        const fields = [
            "user_name",
            "points",
            "winning_points",
            "pana",
            "bid_tx_id"
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const istDate = moment_timeZone.tz(predictionDate, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const matchFilter = {
            gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            pay_status: 0,
            bid_date: { $gte: startDate, $lte: endDate },
        };

        const sumDigits = (str) =>
            str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0);

        const selected_number_sum = sumDigits(selected_number);
        const selected_number_int = parseInt(selected_number, 10);

        // Add digit-based match logic to aggregation pipeline
        const matchDigitLogic = {
            $match: {
                $expr: {
                    $switch: {
                        branches: [
                            {
                                case: { $eq: ["$pana", "Left Digit"] },
                                then:
                                    { $eq: [{ $toInt: "$digits" }, selected_number_sum] }
                            },
                            {
                                case: { $eq: ["$pana", "Right Digit"] },
                                then:
                                    { $eq: [{ $toInt: "$digits" }, selected_number_sum] }
                            },
                            {
                                case: { $in: ["$pana", ["Jodi Digit", "Group Jodi", "Red Bracket"]] },
                                then: {
                                    $eq: [{ $toInt: "$digits" }, selected_number_int]
                                }
                            }

                        ],
                        default: false
                    }
                }
            }
        };

        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            {
                $lookup: {
                    from: "gali_disswar_games",
                    localField: "gameDB_id",
                    foreignField: "_id",
                    as: "gameData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    points: 1,
                    winning_points: 1,
                    pana: 1,
                    bid_tx_id: 1,
                    pay_status: 1,
                    digits: 1,
                    user_name: "$userData.user_name"
                }
            },
            matchDigitLogic
        ];

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$winning_points" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr, totalsArr] = await Promise.all([
            gali_disswar_bid_history_module.aggregate(pipelineWithPagination),
            gali_disswar_bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
            gali_disswar_bid_history_module.aggregate([
                ...basePipeline,
                {
                    $group: {
                        _id: null,
                        total_winning_points: { $sum: "$winning_points" },
                        total_bid_amount: { $sum: "$points" }
                    }
                }
            ])
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        const total_winning_points = totalsArr[0]?.total_winning_points || 0;
        const total_bid_amount = totalsArr[0]?.total_bid_amount || 0;

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            total_winning_points,
            total_bid_amount,
            data: results,
            limit
        });
    } catch (err) {
        console.error("getGalidisswarWinnerList Error:", err);
        return res.status(500).json({ success: false, msg: "Server error: " + err.message });
    }
};

const getMiniGamesList = async (req, res) => {
    try {
        const gamesName = await mini_games_module.find({}).lean();
        return res.json({ success: true, gamesName });
    } catch (error) {
        console.error('getMiniGamesList Error:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getDashboardTopData = async (req, res) => {
    try {
        // Get today's start and end in IST
        const startDate = moment_timeZone.tz("Asia/Kolkata").startOf("day").toDate();
        const endDate = moment_timeZone.tz("Asia/Kolkata").endOf("day").toDate();
        const yesDate = moment_timeZone.tz("Asia/Kolkata").subtract(1, 'day').startOf("day").toDate();
        console.log("today date-", startDate, endDate)
        const total_users_count = await user_module.countDocuments({ status: 1 });
        const games_count = await games_module.countDocuments({});
        const starline_games_count = await starline_games_module.countDocuments({});
        const gali_disswar_games_count = await gali_disswar_games_module.countDocuments({});

        const today_totalBidAmount = await bid_history_module.aggregate([
            {
                $match: {
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$points" }
                }
            }
        ]);

        const totalBidAmount = await bid_history_module.aggregate([
            {
                $group: {
                    _id: null,
                    total: { $sum: "$points" }
                }
            }
        ]);
        const today_totalwinAmount = await wallet_trans_history_module.aggregate([

            {
                $match: {
                    amount_status: { $eq: 8 },
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount_status" }
                }
            }
        ])
        const total_winAmount = await wallet_trans_history_module.aggregate([
            {
                $match: {
                    amount_status: { $eq: 8 }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount_status" }
                }
            }
        ])
        const today_totalBidAmount_starline = await starline_bid_history_module.aggregate([
            {
                $match: {
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$points" }
                }
            }
        ]);

        const totalBidAmount_starline = await starline_bid_history_module.aggregate([
            {
                $group: {
                    _id: null,
                    total: { $sum: "$points" }
                }
            }
        ]);

        const today_totalBidAmount_gali_disswar = await gali_disswar_games_module.aggregate([
            {
                $match: {
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$points" }
                }
            }
        ]);

        const totalBidAmount_gali_disswar = await gali_disswar_games_module.aggregate([
            {
                $group: {
                    _id: null,
                    total: { $sum: "$points" }
                }
            }
        ]);

        const today_totalWithdraw_amount = await withdraw_fund_request_module.aggregate([
            {
                $match: {
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount" }
                }
            }
        ]);

        const today_totalDeposit_amount = await add_funds_module.aggregate([
            {
                $match: {
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount" }
                }
            }
        ]);

        const wallet_balance = await user_module.aggregate([
            {
                $group: {
                    _id: null,
                    total: { $sum: "$wallet_balance" }
                }
            }
        ])
        const zero_balance = await user_module.aggregate([
            {
                $match: { "wallet_balance": { $eq: 0 } }
            },
            { $count: 'total' }
        ])
        const banned_users = await user_module.aggregate([
            {
                $match: { "status": { $eq: 0 } }
            },
            { $count: 'total' }
        ])


        const today_registered = await user_module.countDocuments({ insert_date: { $gte: startDate, $lte: endDate } })
        const today_registered_zb = await user_module.countDocuments({ insert_date: { $gte: startDate, $lte: endDate }, wallet_balance: 0 })
        const today_registered_b = await user_module.countDocuments({ insert_date: { $gte: startDate, $lte: endDate }, wallet_balance: { $ne: 0 } })
        const yesterday_registered = await user_module.countDocuments({ insert_date: { $gte: yesDate, $lte: startDate } })
        const logged_in = await user_module.countDocuments({ logout_status: 0 })
        // console.log("yesterday registered-", startDate.getDate(), yesDate   )
        const gamesName = await games_module.find({ status: 1 }).lean();

        const today_admin_deposit = await wallet_trans_history_module.aggregate([
            {
                $match: {
                    amount_status: 1,
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: '$amount' }
                }
            }
        ])
        const today_admin_withdraw = await wallet_trans_history_module.aggregate([
            {
                $match: {
                    amount_status: 2,
                    insert_date: { $gte: startDate, $lte: endDate }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: '$amount' }
                }
            }
        ])


        // 10k, 10.06k, 1.2M, 3.45B â€¦
        function formatCount(n) {
            if (n == null) return '0';

            const abs = Math.abs(n);
            const sign = n < 0 ? '-' : '';

            const units = [
                { value: 1e12, suffix: 'T' },
                { value: 1e9, suffix: 'B' },
                { value: 1e6, suffix: 'M' },
                { value: 1e3, suffix: 'k' },
            ];

            for (const u of units) {
                if (abs >= u.value) {
                    const num = abs / u.value;
                    // keep up to 2 decimals, strip trailing zeros (so 10.00k -> 10k, 10.06k stays)
                    const str = num.toFixed(2).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1');
                    return sign + str + u.suffix;
                }
            }

            return String(n);
        }

        let total_bid_amount = () => {
            const total =
                (totalBidAmount[0]?.total || 0) +
                (totalBidAmount_starline[0]?.total || 0) +
                (totalBidAmount_gali_disswar[0]?.total || 0);

            return formatCount(total);
        };
        console.log("bid amout")
        return res.json({
            success: true,
            total_users: total_users_count,
            total_lobby_games: games_count,
            total_starline_games: starline_games_count,
            total_galidisswar_games: gali_disswar_games_count,
            today_total_bid_amount: (today_totalBidAmount[0]?.total || 0) + (today_totalBidAmount_starline[0]?.total || 0) + (today_totalBidAmount_gali_disswar[0]?.total || 0),
            total_bid_amount: total_bid_amount(),
            today_total_withdraw: today_totalWithdraw_amount[0]?.total || 0,
            today_total_deposit: today_totalDeposit_amount[0]?.total || 0,
            total_winning_amount: total_winAmount[0]?.total || 0,
            today_winning_amount: today_totalwinAmount[0]?.total || 0,
            today_profit: today_totalBidAmount[0]?.total - today_totalwinAmount[0]?.total || 0,
            total_profit: ((totalBidAmount[0]?.total || 0) + (totalBidAmount_starline[0]?.total || 0) + (totalBidAmount_gali_disswar[0]?.total || 0)) - total_winAmount[0]?.total || 0,
            total_wallet_balance: wallet_balance[0]?.total || 0,
            zero_balance_users: zero_balance[0]?.total || 0,
            banned_users: banned_users[0]?.total || 0,
            today_registered_users: today_registered || 0,
            today_register_with_balance: today_registered_b || 0,
            today_register_with_zero_balance: today_registered_zb || 0,
            yesterday_registered_users: yesterday_registered || 0,
            today_admin_deposit: today_admin_deposit[0]?.total || 0,
            today_admin_withdraw: today_admin_withdraw[0]?.total || 0,
            logged_in_users: logged_in || 0

        });
    } catch (error) {
        console.error('getDashboardTopData Error:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getSearchMarketBidDetails = async (req, res) => {
    try {
        const gameDB_id = (req?.body?.gameDB_id || '').trim();
        const session = (req?.body?.session || '').trim();
        const cur_date = new Date();
        const startDate = new Date(cur_date.setHours(0, 0, 0, 0));
        const endDate = new Date(cur_date.setHours(23, 59, 59, 999));

        if (!gameDB_id || !session) {
            return res.status(400).json({ success: false, msg: "Game ID and market status are required." });
        }

        const excludePanas = ['Jodi Digit', 'Half Sangam', 'Full Sangam'];

        const query = {
            bid_date: {
                $gte: startDate,
                $lte: endDate
            },
            gameDB_id,
            session,
            pana: { $nin: excludePanas }
        };

        const getBidHistory = await bid_history_module.find(query);

        const numberWords = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];

        const results = {
            total_zero: 0, total_one: 0, total_two: 0, total_three: 0, total_four: 0,
            total_five: 0, total_six: 0, total_seven: 0, total_eight: 0, total_nine: 0,
            bid_zero: 0, bid_one: 0, bid_two: 0, bid_three: 0, bid_four: 0,
            bid_five: 0, bid_six: 0, bid_seven: 0, bid_eight: 0, bid_nine: 0
        };

        for (const bid of getBidHistory) {
            let win_number = null;
            const digits = bid?.digits || '';
            const pana = bid?.pana || '';
            const points = typeof bid?.points === 'number' ? bid.points : 0;

            if (['Single Pana', 'Double Pana', 'Triple Pana'].includes(pana)) {
                if (digits.length === 3 && /^\d{3}$/.test(digits)) {
                    const sum = parseInt(digits[0]) + parseInt(digits[1]) + parseInt(digits[2]);
                    win_number = sum % 10;
                } else {
                    continue;
                }
            } else {
                const num = parseInt(digits);
                if (!isNaN(num)) {
                    win_number = num % 10;
                } else {
                    continue;
                }
            }

            const word = numberWords[win_number];
            results[`total_${word}`] += points;
            results[`bid_${word}`] += 1;
        }

        return res.json({ success: true, ...results });

    } catch (error) {
        console.error("Error in getSearchBidDetails:", error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const getMarketBidDetails = async (req, res) => {
    try {
        const gameDB_id = (req?.body?.gameDB_id || "").trim();
        const cur_date = new Date();
        const startDate = new Date(cur_date.setHours(0, 0, 0, 0));
        const endDate = new Date(cur_date.setHours(23, 59, 59, 999));

        if (!gameDB_id) {
            return res.status(400).json({ success: false, msg: "Game ID is required." });
        }

        if (!mongoose.isValidObjectId(gameDB_id) && gameDB_id.toLowerCase() !== 'all') {
            return res.status(400).json({ success: false, msg: "Invalid Game ID." });
        }

        const where = {
            bid_date: {
                $gte: startDate,
                $lte: endDate
            }
        };
        if (gameDB_id && gameDB_id.toLowerCase() !== 'all') {
            where.gameDB_id = gameDB_id;
        }

        const getBidHistory = await bid_history_module.find(where);

        const total_points = getBidHistory.reduce((sum, bid) => {
            return sum + (typeof bid.points === 'number' ? bid.points : 0);
        }, 0);

        return res.json({
            success: true,
            points: total_points
        });

    } catch (error) {
        console.error("Error in getMarketBidDetails:", error);
        return res.status(500).json({
            success: false,
            msg: 'Internal Server Error'
        });
    }
};

const galidisswarResultHistoryListLoadData = async (req, res) => {
    try {
        let { result_dec_date } = req.body;

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const gamesName = await gali_disswar_games_module.find({}, 'game_name');

        const matchStage = result_dec_date
            ? { result_date: { $gte: startDate, $lte: endDate } }
            : {};

        const results = await gali_disswar_game_result_history_module.aggregate([
            {
                $match: matchStage
            },
            {
                $lookup: {
                    from: 'gali_disswar_games',
                    localField: 'gameDB_id',
                    foreignField: '_id',
                    as: 'game'
                }
            },
            {
                $unwind: {
                    path: '$game',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $project: {
                    _id: 1,
                    gameDB_id: 1,
                    result_date: 1,
                    close_decleare_date: 1,
                    game_name: '$game.game_name',
                    close_number: 1,
                    close_decleare_status: 1,
                }
            }
        ]);

        const data = results.map((rs) => {
            const gameDB_id = rs.gameDB_id;

            // close result logic
            let close_result = '';
            let close_date = rs?.close_decleare_date ? moment_timeZone(rs?.close_decleare_date).tz('Asia/Kolkata').format('DD MMM YYYY') : 'N/A';
            if (rs.close_number) {
                const close_num_sum = rs.close_number.split('').reduce((sum, val) => sum + parseInt(val), 0);
                const close_final_digit = close_num_sum % 10;

                close_result = `${rs.close_number}-${close_final_digit}`;
            }

            return {
                game_name: rs?.game_name || 'N/A',
                result_date: moment_timeZone(rs.result_date).tz('Asia/Kolkata').format('DD MMM YYYY') || 'N/A',
                result_date_long: rs?.result_date || '',
                close_result,
                close_date,
                gameDB_id
            };
        });

        return res.json({ data, gamesName, success: true });
    } catch (error) {
        console.error('Error loading result history:', error);
        res.status(500).json({ success: false, error: 'Something went wrong' });
    }
};

const getDecleareGalidisswarGameData = async (req, res) => {
    try {
        const gameDB_id = req.body.gameDB_id?.trim();
        const result_dec_date = req.body.result_dec_date?.trim();

        if (!gameDB_id || !result_dec_date) {
            return res.status(400).json({ success: false, message: 'Missing gameDB_id or result_dec_date' });
        }

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        let matchQuery = {
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate },
            close_number: { $exists: true }
        };

        const result = await gali_disswar_game_result_history_module.findOne(matchQuery);

        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        let data = {
            success: true,
            is_close_declare: result?.close_decleare_status === 1 ? true : false,
        };

        data.close_number = result?.close_number || '';
        data.auto_digit = result?.close_number
            ? String(sumDigits_with_reminder(result.close_number))
            : '';
        res.json(data);
    } catch (err) {
        console.error('Error:', err);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const saveGalidisswarGameData = async (req, res) => {
    try {
        const {
            pana_number = "",
            gameDB_id = "",
            result_dec_date = "",
            auto_digit = ""
        } = req.body;

        // Check for required fields
        if (!pana_number || !gameDB_id || !result_dec_date || !auto_digit) {
            return res.status(400).json({ status: 'fail', msg: 'Missing required fields' });
        }

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        // Prepare insert and query objects
        const insertData = {
            gameDB_id,
            result_date: istDate,
            close_number: pana_number
        };

        const where = {
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate },
        };

        // Check if result already exists
        let existing = await gali_disswar_game_result_history_module.findOne(where).populate('gameDB_id');

        if (existing) {
            existing.close_number = pana_number;
            await existing.save()
            return res.json({ success: true });
        }

        // Create new record
        await gali_disswar_game_result_history_module.create(insertData);

        return res.json({ success: true });
    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: 'Server error' });
    }
};

const getGalidisswarWinnerList_declare = async (req, res) => {
    try {
        const { gameDB_id, result_dec_date } = req.body

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const result = await gali_disswar_game_result_history_module.find({
            close_number: { $ne: '0' },
            gameDB_id,
            result_date: { $gte: startDate, $lte: endDate }
        }).lean()

        if (result.length <= 0) {
            return res.status(400).json({ success: false, msg: "Please save game result first" })
        }

        const game_rate = await gali_disswar_game_rates_module.findOne().lean()
        const [data] = await Promise.all(result.map(async (item) => {
            const close_number = item.close_number

            const red_bracket_val_1 = game_rate.red_bracket_val_1;
            const group_jodi_val_1 = game_rate.group_jodi_val_1;
            const jodi_digit_val_1 = game_rate.jodi_digit_val_1;
            const red_bracket_val_2 = game_rate.red_bracket_val_2;
            const group_jodi_val_2 = game_rate.group_jodi_val_2;
            const jodi_digit_val_2 = game_rate.jodi_digit_val_2;

            const bid_data = await gali_disswar_bid_history_module.aggregate([
                {
                    $match: {
                        gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                        pay_status: 0,
                        bid_date: { $gte: startDate, $lte: endDate },
                        session: { $ne: "Open" }
                    }
                }, {
                    $lookup: {
                        from: "gali_disswar_games",
                        localField: "gameDB_id",
                        foreignField: "_id",
                        as: "game"
                    }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "userDB_id",
                        foreignField: "_id",
                        as: "user",
                    },
                },
                {
                    $unwind: {
                        path: "$game",
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $unwind: {
                        path: "$user",
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $project: {
                        game_name: "$game.game_name",
                        userDB_id: "$user._id",
                        user_name: "$user.user_name",
                        pana: 1,
                        digits: 1,
                        points: 1,
                        bid_id: "$_id",
                        bid_tx_id: 1,
                        pay_status: 1,
                        close_result_token: 1,
                    },
                },
            ])

            const data_array = []
            let win_amt_sum = 0
            let points_amt_sum = 0

            bid_data.forEach(async (item, i) => {
                let win_amount = 0
                let points = 0
                if (item.pana == 'Jodi Digit') {
                    if (close_number == item.digits) {
                        win_amount = (jodi_digit_val_2 / jodi_digit_val_1) * item.points;
                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }

                } else if (item.pana == 'Group Jodi') {
                    if (close_number == item.digits) {
                        win_amount = (group_jodi_val_2 / group_jodi_val_1) * item.points;
                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }

                } else if (item.pana == 'Red Bracket') {
                    if (close_number == item.digits) {
                        win_amount = (red_bracket_val_2 / red_bracket_val_1) * item.points;
                        points = item.points;

                        data_array.push({
                            points: item?.points,
                            userDB_id: item?.userDB_id,
                            user_name: item?.user_name,
                            pana: item?.pana,
                            bid_tx_id: item?.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                }

                win_amt_sum += win_amount;
                points_amt_sum += points;
            })

            return {
                data: data_array,
                point: points_amt_sum,
                win_amt: win_amt_sum
            }
        }))
        res.status(200).json({ success: true, data: data.data, point: data.point, win_amt: data.win_amt })
    } catch (err) {
        console.error('getOpenWinnerList error:', err);
        return res.status(500).json({
            success: false,
            msg: "Server error"
        });
    }
};

const decleareGalidisswarData = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { result_dec_date, gameDB_id } = req.body;

        const resultDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = resultDate.clone().startOf("day").toDate();
        const endDate = resultDate.clone().endOf("day").toDate();

        const result = await gali_disswar_game_result_history_module.findOne({
            gameDB_id,
            close_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }).session(session);

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Please save game result first" });
        }

        if (result.close_decleare_status == 1) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Result already declared" });
        }

        const close_number = result.close_number;

        let win_number_not = close_number.toString().split("").reduce((acc, curr) => acc + Number(curr), 0) % 10;

        const game_rate = await gali_disswar_game_rates_module.findOne({}).session(session);

        const left_digit_val_1 = game_rate.left_digit_val_1;
        const right_digit_val_1 = game_rate.right_digit_val_1;
        const jodi_digit_val_1 = game_rate.jodi_digit_val_1;
        const left_digit_val_2 = game_rate.left_digit_val_2;
        const right_digit_val_2 = game_rate.right_digit_val_2;
        const jodi_digit_val_2 = game_rate.jodi_digit_val_2;

        const close_result_token = uniqRandom(15);

        const result_bid = await gali_disswar_bid_history_module.aggregate([
            {
                $match: {
                    gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
                    pay_status: 0,
                    bid_date: { $gte: startDate, $lte: endDate },
                    session: { $ne: "Open" }
                }
            },
            {
                $lookup: {
                    from: "gali_disswar_games",
                    localField: "gameDB_id",
                    foreignField: "_id",
                    as: "game"
                }
            },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "user",
                },
            },
            { $unwind: "$game" },
            { $unwind: "$user" },
            {
                $project: {
                    game_name: "$game.game_name",
                    userDB_id: "$user._id",
                    user_name: "$user.user_name",
                    pana: 1,
                    digits: 1,
                    points: 1,
                    bid_id: "$_id",
                    bid_tx_id: 1,
                    pay_status: 1,
                    close_result_token: 1,
                }
            }
        ]).session(session);

        for (const item of result_bid) {
            const { pana, digits, points, bid_tx_id, userDB_id } = item;
            let win_amt = 0, matched = false;

            const winSingleDigit = close_number.toString().split('').reduce((a, b) => a + Number(b), 0) % 10;

            switch (pana) {
                case 'Left Digit':
                    if (winSingleDigit == digits) {
                        win_amt = (left_digit_val_2 / left_digit_val_1) * item.points;
                        matched = true;
                    }
                    break;
                case 'Right Digit':
                    if (winSingleDigit == digits) {
                        win_amt = (right_digit_val_2 / right_digit_val_1) * item.points;
                        matched = true;
                    }
                    break;
                case 'Group Jodi':
                case 'Red Bracket':
                case 'Jodi Digit':
                    if (close_number == digits) {
                        win_amt = (jodi_digit_val_2 / jodi_digit_val_1) * item.points;
                        matched = true;
                    }
                    break;
            }

            if (matched) {
                const msg = `${item.game_name} in ${pana} for bid amount- ${points} Won`;
                const tx_token = getUserRandomToken();

                await Promise.all([
                    user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: win_amt } },
                        { new: true, session }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        amount: win_amt,
                        transaction_type: 1,
                        amount_status: 8,
                        transaction_note: msg,
                        tx_request_number: tx_token,
                        bid_tx_id,
                        close_result_token
                    }).save({ session }),

                    gali_disswar_bid_history_module.updateOne(
                        { _id: item.bid_id },
                        { $set: { pay_status: 1, close_result_token } },
                        { session }
                    ),

                    new user_notification_module({
                        userDB_id,
                        msg: `Congratulations ,You Won in ${item.game_name} for Bid Number- ${bid_tx_id}`,
                    }).save({ session })
                ]);
            } else {
                await gali_disswar_bid_history_module.updateOne({ _id: item.bid_id }, { $set: { pay_status: 2 } }, { session });
            }
        }

        await gali_disswar_game_result_history_module.updateOne({
            gameDB_id,
            close_number: { $ne: '0' },
            result_date: { $gte: startDate, $lte: endDate }
        }, {
            $set: {
                close_decleare_status: 1,
                close_decleare_date: new Date(),
                close_result_token
            }
        }, { session });

        const usersData = await user_module.find({ notification_status: 1 }).session(session);

        for (const user of usersData) {
            const notification_content = `${close_number}-${win_number_not}`;
            await new user_notification_module({ userDB_id: user._id, msg: notification_content }).save({ session });
        }

        await session.commitTransaction();
        session.endSession();
        return res.status(200).json({ success: true, message: "Close result declared successfully" });

    } catch (err) {
        console.error("declareData error:", err);
        return res.status(500).json({
            success: false,
            msg: "Server error"
        });
    }
};

const getGalidisswarWinningReport = async (req, res) => {
    try {
        const gameDB_id = req?.body?.gameDB_id?.trim() || "";
        const result_dec_date = req?.body?.result_dec_date?.trim() || "";

        if (!result_dec_date || !gameDB_id) {
            return res.status(400).json({
                success: false,
                msg: 'Missing required fields.'
            });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        const pipeline = [
            {
                $match: {
                    result_date: {
                        $gte: startDate,
                        $lte: endDate
                    }
                }
            },
            {
                $lookup: {
                    from: 'wallet_trans_histories',
                    localField: 'close_result_token',
                    foreignField: 'close_result_token',
                    as: 'wallet',
                },
            },
            {
                $unwind: {
                    path: '$wallet',
                },
            },
            {
                $lookup: {
                    from: 'gali_disswar_bid_histories',
                    localField: 'wallet.bid_tx_id',
                    foreignField: 'bid_tx_id',
                    as: 'bid',
                },
            },
            {
                $unwind: {
                    path: '$bid',
                },
            },
            {
                $match: {
                    'bid.gameDB_id': new mongoose.Types.ObjectId(gameDB_id),
                },
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'bid.userDB_id',
                    foreignField: '_id',
                    as: 'user',
                },
            },
            {
                $unwind: {
                    path: '$user',
                },
            },
            {
                $project: {
                    user_name: '$user.user_name',
                    user_id: '$wallet.userDB_id',
                    game_name: '$bid.game_name',
                    session: '$bid.session',
                    winning_points: '$bid.winning_points',
                    transaction_note: '$wallet.transaction_note',
                    tx_request_number: '$wallet.tx_request_number',
                    insert_date: '$wallet.insert_date',
                    pana: '$bid.pana',
                    digits: '$bid.digits',
                    closedigits: '$bid.closedigits',
                    points: '$bid.points',
                    bid_id: '$bid._id',
                    bid_tx_id: '$bid.bid_tx_id',
                },
            },
            {
                $sort: { transaction_id: 1 },
            },
        ];

        const result = await gali_disswar_game_result_history_module.aggregate(pipeline);
        res.json({ success: true, getResultHistory: result });
    } catch (err) {
        console.error(err);
        res.status(500).json({ success: false, error: 'Something went wrong' });
    }
};

const getWinningHistoryData = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            result_dec_date,
            gameDB_id = "",
            selected_session = ""
        } = req.body;

        const fields = [
            "user_name",
            "bid_tx_id",
            "pana",
            "session",
            "digits",
            "digits",
            "digits",
            "digits",
            "points",
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const prediction = moment_timeZone.tz(result_dec_date?.trim(), 'Asia/Kolkata');

        const startDate = prediction.clone().startOf('day').toDate();
        const endDate = prediction.clone().endOf('day').toDate();

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }

        const gameResult = await game_result_history_module.findOne({
            gameDB_id,
            result_date: {
                $gte: startDate,
                $lte: endDate
            }
        }).lean();

        if (!gameResult) {
            return res.json({
                success: true,
                recordsFiltered: 0,
                data: [],
                limit
            });
        }

        const {
            open_decleare_status,
            close_decleare_status,
            open_result_token,
            close_result_token
        } = gameResult;

        let matchConditions = {
            insert_date: {
                $gte: startDate,
                $lte: endDate
            },
        };

        if (selected_session === 'Open') {
            if (open_decleare_status !== 1) return res.json({
                success: true,
                recordsFiltered: 0,
                data: [],
                limit
            });

            matchConditions['open_result_token'] = open_result_token;
        } else {
            if (close_decleare_status !== 1) return res.json({
                success: true,
                recordsFiltered: 0,
                data: [],
                limit
            });

            matchConditions['close_result_token'] = close_result_token;
        }

        const basePipeline = [
            { $match: matchConditions },
            {
                $lookup: {
                    from: 'bid_histories',
                    localField: 'bid_tx_id',
                    foreignField: 'bid_tx_id',
                    as: 'bid'
                }
            },
            { $unwind: '$bid' },
            { $match: { 'bid.gameDB_id': new mongoose.Types.ObjectId(gameDB_id) } },
            {
                $lookup: {
                    from: 'users',
                    localField: 'bid.userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            { $unwind: '$user' },
            {
                $project: {
                    user_name: '$user.user_name',
                    game_name: '$bid.game_name',
                    session: '$bid.session',
                    winning_points: '$bid.winning_points',
                    tx_request_number: 1,
                    insert_date: 1,
                    pana: '$bid.pana',
                    digits: '$bid.digits',
                    closedigits: '$bid.closedigits',
                    points: '$bid.points',
                    _id: 1,
                    bid_tx_id: '$bid.bid_tx_id'
                }
            },
        ];

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        { session: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$winning_points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$tx_request_number" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$digits" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            wallet_trans_history_module.aggregate(pipelineWithPagination),
            wallet_trans_history_module.aggregate([...basePipeline, { $count: "total" }]),
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        const data = results.map((v) => {
            const common = {
                _id: v._id,
                points: v.points,
                pana: v.pana,
                winning_points: v.winning_points,
                game_name: v.game_name,
                tx_request_number: v.tx_request_number,
                insert_date: v?.insert_date ? formatDateToDDMMYYYY(v.insert_date) : 'N/A',
                session: v.session,
                bid_tx_id: v.bid_tx_id,
                user_name: v.user_name,
            };

            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };

                case 'Jodi Digit':
                case 'Group Jodi':
                case 'Red Bracket': {
                    const padded = String(v.digits).padStart(2, '0');
                    return {
                        ...common,
                        open_digit: padded[0],
                        close_digit: padded[1],
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
                }

                case 'Full Sangam':
                    return {
                        ...common,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                    };

                case 'Half Sangam':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                        close_pana: v.session === 'Open' ? v.closedigits : 'N/A',
                    };

                case 'Single Pana':
                case 'Double Pana':
                case 'Triple Pana':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? sumDigits_with_reminder(String(v.digits)) : 'N/A',
                        close_digit: v.session === 'Close' ? sumDigits_with_reminder(String(v.digits)) : 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.digits : v.closedigits,
                    };

                default:
                    return {
                        ...common,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
            }
        });

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });
    } catch (err) {
        console.error('Error in getWinningHistoryData:', err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
};

// const getBidWinningReportDetails = async (req, res) => {
//     try {
//         const result_dec_start_date = req.body.result_dec_start_date?.trim();
//         const result_dec_end_date = req.body.result_dec_end_date?.trim();

//         let filter = {};
//         let matchCondition = { amount_status: 8 }; // wallet_trans_history ke liye

//         // Agar date di gayi hai tabhi filter add karna
//         if (result_dec_start_date && result_dec_end_date) {
//             const start_date = moment_timeZone.tz(result_dec_start_date, "Asia/Kolkata");
//             const startDate = start_date.clone().startOf("day").toDate();

//             const end_date = moment_timeZone.tz(result_dec_end_date, "Asia/Kolkata");
//             const endDate = end_date.clone().endOf("day").toDate();

//             filter.bid_date = { $gte: startDate, $lte: endDate };
//             matchCondition.insert_date = { $gte: startDate, $lte: endDate };
//         }

//         // âœ… 1. Bid details
//         const bid_details = await bid_history_module.find(filter).lean();

//         let total_bid_amt = 0;
//         let total_win_amt = 0;
//         let total_profit_amt = 0;
//         let total_loss_amt = 0;

//         if (bid_details.length > 0) {
//             total_bid_amt = bid_details.reduce((sum, bid) => sum + parseFloat(bid.points || 0), 0);
//         }

//         // âœ… 2. Win details from wallet_trans_history with optional date filter
//         const win_details = await wallet_trans_history_module.aggregate([
//             { $match: matchCondition },
//             {
//                 $lookup: {
//                     from: "bid_histories",
//                     localField: "bid_tx_id",
//                     foreignField: "bid_tx_id",
//                     as: "bid"
//                 }
//             },
//             { $unwind: "$bid" },
//             {
//                 $project: {
//                     _id: 0,  
//                     winning_points: "$bid.winning_points",
//                     wining_date: {
//                         $dateToString: {
//                             format: "%d %B %Y %H:%M",
//                             date: "$insert_date"
//                         }
//                     },
//                     game_name: "$bid.game_name",
//                     pana: "$bid.pana",
//                     session: "$bid.session"
//                 }
//             }
//         ]);


//         if (win_details.length > 0) {
//             total_win_amt = win_details.reduce((sum, item) => sum + parseFloat(item?.winning_points || 0), 0);
//         }

//         // âœ… 3. Profit or Loss Calculation
//         if (total_bid_amt > total_win_amt) {
//             total_profit_amt = total_bid_amt - total_win_amt;
//         } else {
//             total_loss_amt = total_win_amt - total_bid_amt;
//         }

//         // âœ… 4. Final Response
//         res.json({
//             success: true,
//             total_bid_amount: total_bid_amt,
//             total_win_amount: total_win_amt,
//             total_profit_amount: total_profit_amt,
//             total_loss_amount: total_loss_amt
//         });
//     } catch (error) {
//         console.error("Error:", error);
//         res.status(500).json({ success: false, message: "Server error" });
//     }
// };



const getBidWinningReportDetails = async (req, res) => {
    try {
        const result_dec_start_date = req.body.result_dec_start_date?.trim();
        const result_dec_end_date = req.body.result_dec_end_date?.trim();
        const selected_gameDB_id = req.body.selected_gameDB_id?.trim();
        const gameType = req.body.gameType?.trim();

        let filter = {};
        let matchCondition = { amount_status: 8 }; // wallet_trans_history ke liye

        // âœ… Date filter
        if (result_dec_start_date && result_dec_end_date) {
            const start_date = moment_timeZone.tz(result_dec_start_date, "Asia/Kolkata");
            const startDate = start_date.clone().startOf("day").toDate();

            const end_date = moment_timeZone.tz(result_dec_end_date, "Asia/Kolkata");
            const endDate = end_date.clone().endOf("day").toDate();
            // console.log("start & end date-", startDate, endDate)
            filter.bid_date = { $gte: startDate, $lte: endDate };
            matchCondition.insert_date = { $gte: startDate, $lte: endDate };
        }
        // âœ… Game filter
        if (selected_gameDB_id) {
            filter.gameDB_id = selected_gameDB_id;           // for bid_history
        }

        // âœ… GameType filter
        if (gameType && gameType !== "all") {
            filter.pana = gameType;           // adjust field based on your schema
            matchCondition["bid.pana"] = gameType;
        }

        // 1. Bid details
        const bid_details = await bid_history_module.find(filter).lean();
        let total_bid_amt = 0;
        let total_win_amt = 0;
        let total_profit_amt = 0;
        let total_loss_amt = 0;

        if (bid_details.length > 0) {
            total_bid_amt = bid_details.reduce((sum, bid) => sum + parseFloat(bid.points || 0), 0);
        }
        console.log("Total Bid Amount:", total_bid_amt);

        // 2. Win details
        console.log("Match Condition for Win Details:", matchCondition);
        const win_details = await wallet_trans_history_module.aggregate([
            { $match: matchCondition },
            {
                $lookup: {
                    from: "bid_histories",
                    localField: "bid_tx_id",
                    foreignField: "bid_tx_id",
                    as: "bid"
                }
            },
            { $unwind: "$bid" },
            // âœ… Apply gameType filter inside aggregation
            ...(gameType && gameType !== "all" ? [{ $match: { "bid.pana": gameType } }] : []),
            {
                $project: {
                    _id: 0,
                    winning_points: "$bid.winning_points",
                    wining_date: {
                        $dateToString: {
                            format: "%d %B %Y %H:%M",
                            date: "$insert_date"
                        }
                    },
                    game_name: "$bid.game_name",
                    pana: "$bid.pana",
                    session: "$bid.session"
                }
            }
        ]);
        console.log("Win Details:", win_details);

        if (win_details.length > 0) {
            total_win_amt = win_details.reduce((sum, item) => sum + parseFloat(item?.winning_points || 0), 0);
        }

        // 3. Profit or Loss
        if (total_bid_amt > total_win_amt) {
            total_profit_amt = total_bid_amt - total_win_amt;
        } else {
            total_loss_amt = total_win_amt - total_bid_amt;
        }

        res.json({
            success: true,
            total_bid_amount: total_bid_amt,
            total_win_amount: total_win_amt,
            total_profit_amount: total_profit_amt,
            total_loss_amount: total_loss_amt,
            win_details: win_details || [],
            bid_details: bid_details || []
        });
    } catch (error) {
        console.error("Error:", error);
        res.status(500).json({ success: false, message: "Server error" });
    }
};



const getBidReportList = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            result_dec_start_date,
            result_dec_end_date,
        } = req.body;

        const fields = [
            "user_name",
            "pana",
            "session",
            "digits",
            "digits",
            "digits",
            "digits",
            "points",
            "bid_tx_id",
            "insert_date"
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        const start_date = result_dec_start_date
            ? moment_timeZone.tz(result_dec_start_date.trim(), 'Asia/Kolkata').startOf('day').toDate()
            : null;

        const end_date = result_dec_end_date
            ? moment_timeZone.tz(result_dec_end_date.trim(), 'Asia/Kolkata').endOf('day').toDate()
            : null;

        let matchFilter = {};

        if (start_date && end_date) {
            matchFilter.insert_date = { $gte: start_date, $lte: end_date };
        }

        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    points: 1,
                    pana: 1,
                    game_name: 1,
                    session: 1,
                    points: 1,
                    insert_date: 1,
                    bid_tx_id: 1,
                    digits: 1,
                    closedigits: 1,
                    user_name: "$userData.user_name"
                }
            },
        ];

        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        { session: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$points" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$digits" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const [results, totalCountArr] = await Promise.all([
            bid_history_module.aggregate(pipelineWithPagination),
            bid_history_module.aggregate([...basePipeline, { $count: "total" }]),
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        const sumDigits_with_reminder = (str) =>
            (str.split("").reduce((sum, digit) => sum + parseInt(digit, 10), 0)) % 10;

        const data = results.map((v) => {
            const common = {
                _id: v._id,
                points: v.points,
                pana: v.pana,
                session: v.session,
                bid_tx_id: v.bid_tx_id,
                user_name: v.user_name,
                insert_date: v.insert_date ? moment_timeZone(v.insert_date).tz('Asia/Kolkata').format('DD-MM-YYYY') : 'N/A',
            };

            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };

                case 'Group Jodi':
                case 'Red Bracket':
                case 'Jodi Digit': {
                    const padded = String(v.digits).padStart(2, '0');
                    return {
                        ...common,
                        open_digit: padded[0],
                        close_digit: padded[1],
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
                }

                case 'Full Sangam':
                    return {
                        ...common,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                    };

                case 'Half Sangam':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                        close_pana: v.session === 'Open' ? v.closedigits : 'N/A',
                    };

                case 'Single Pana':
                case 'Double Pana':
                case 'Triple Pana':
                    return {
                        ...common,
                        open_digit: v.session === 'Open' ? sumDigits_with_reminder(String(v.digits)) : 'N/A',
                        close_digit: v.session === 'Close' ? sumDigits_with_reminder(String(v.digits)) : 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.digits : (v.closedigits || 'N/A'),
                    };

                default:
                    return {
                        ...common,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
            }
        });

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (error) {
        console.error("Error:", error);
        res.status(500).json({ status: "error", message: "Server error" });
    }
};

// const getWinningReportDetails = async (req, res) => {
//     try {
//         const {
//             length = 10,
//             start = 1,
//             fieldIndex = 0,
//             order = -1,
//             searchValue = "",
//             selected_start_date,
//             selected_end_date,
//         } = req.body;

//         const fields = [
//             "user_name", "pana", "session",
//             "digits", "digits", "digits", "digits", "", "points", "tx_request_number", "winning_points", "", "bid_tx_id", "insert_date"
//         ];

//         const limit = parseInt(length);
//         const page = parseInt(start);
//         const skip = !searchValue && page !== 0 ? (page - 1) : 0;
//         const orderField = fields[fieldIndex] || "insert_date";
//         const orderDir = parseInt(order);
//         const searchTerm = searchValue.trim();
//         console.log("orderField-", orderField)
//         let startDate = null;
//         let endDate = null;

//         console.log("selected_start_date", selected_start_date)

//         if (selected_start_date && selected_end_date) {
//             startDate = moment_timeZone
//                 .tz(selected_start_date.trim(), "Asia/Kolkata")
//                 .startOf("day")
//                 .toDate();

//             endDate = moment_timeZone
//                 .tz(selected_end_date.trim(), "Asia/Kolkata")
//                 .endOf("day")
//                 .toDate();
//         }

//         console.log("ðŸš€ ~ getWinningReportDetails ~ startDate:", startDate)
//         console.log("ðŸš€ ~ getWinningReportDetails ~ endDate:", endDate)

//         let gameResult = null;

//         if (startDate && endDate) {
//             gameResult = await game_result_history_module.findOne({
//                 result_date: { $gte: startDate, $lte: endDate }
//             }).lean();
//         } else {
//             gameResult = await game_result_history_module.findOne({}).lean();
//         }

//         if (!gameResult) return res.json({ success: true, data: [], recordsFiltered: 0 });

//         const { open_result_token, close_result_token } = gameResult;

//         const matchConditions = {};

//         if (startDate && endDate) {
//             matchConditions.insert_date = { $gte: startDate, $lte: endDate };
//         }

//         // const basePipeline2 = [
//         //     { $match: { 'insert_date': { $gte: startDate, $lte: endDate } } },
//         //     { $match: { 'amount_status': { $eq: 5 } } },
//         //     {
//         //         $lookup: {
//         //             from: 'bid_histories',
//         //             localField: 'bid_tx_id',
//         //             foreignField: 'bid_tx_id',
//         //             as: 'bid'
//         //         }
//         //     },
//         //     { $unwind: "$bid" },
//         //     {
//         //         $project: {
//         //             points: '$bid.points',
//         //             insert_date: 1
//         //         }
//         //     }

//         // ]
//         // console.log("Game result - ", { open_result_token }, { close_result_token })
//         // console.log("basePipeline2-", basePipeline2)
//         // const [ans] = await Promise.all([wallet_trans_history_module.aggregate(basePipeline2)])
//         // console.log("result -", ans)


//         matchConditions.$or = [
//             { open_result_token },
//             { close_result_token }
//         ];

//         const bid_amt_filter = {
//             ...matchConditions,
//             'amount_status': { $eq: 5 }
//         }

//         const win_amt_filter = {
//             ...matchConditions,
//             'amount_status': { $eq: 8 }
//         }

//         const basePipeline = [
//             { $match: win_amt_filter },
//             {
//                 $lookup: {
//                     from: 'bid_histories',
//                     localField: 'bid_tx_id',
//                     foreignField: 'bid_tx_id',
//                     as: 'bid'
//                 }
//             },
//             { $unwind: '$bid' },
//             {
//                 $lookup: {
//                     from: 'users',
//                     localField: 'bid.userDB_id',
//                     foreignField: '_id',
//                     as: 'user'
//                 }
//             },
//             { $unwind: '$user' },
//             {
//                 $project: {
//                     user_name: '$user.user_name',
//                     game_name: '$bid.game_name',
//                     session: '$bid.session',
//                     winning_points: '$bid.winning_points',
//                     tx_request_number: 1,
//                     insert_date: 1,
//                     pana: '$bid.pana',
//                     digits: '$bid.digits',
//                     closedigits: '$bid.closedigits',
//                     points: '$bid.points',
//                     _id: 1,
//                     bid_tx_id: '$bid.bid_tx_id'
//                 }
//             }
//         ];
//         const basePipeline2 = [
//             { $match: bid_amt_filter },
//             {
//                 $lookup: {
//                     from: 'bid_histories',
//                     localField: 'bid_tx_id',
//                     foreignField: 'bid_tx_id',
//                     as: 'bid'
//                 }
//             },
//             { $unwind: '$bid' },
//             {
//                 $lookup: {
//                     from: 'users',
//                     localField: 'bid.userDB_id',
//                     foreignField: '_id',
//                     as: 'user'
//                 }
//             },
//             { $unwind: '$user' },
//             {
//                 $project: {
//                     user_name: '$user.user_name',
//                     game_name: '$bid.game_name',
//                     session: '$bid.session',
//                     winning_points: '$bid.winning_points',
//                     tx_request_number: 1,
//                     insert_date: 1,
//                     pana: '$bid.pana',
//                     digits: '$bid.digits',
//                     closedigits: '$bid.closedigits',
//                     points: '$bid.points',
//                     _id: 1,
//                     bid_tx_id: '$bid.bid_tx_id'
//                 }
//             }
//         ];
//         // const [ans] = await Promise.all([wallet_trans_history_module.aggregate(basePipeline)])
//         // console.log("result -", ans)


//         if (searchTerm) {
//             const regex = new RegExp(`^${searchTerm}`, "i");
//             basePipeline.push({
//                 $match: {
//                     $or: [
//                         { user_name: { $regex: regex } },
//                         { pana: { $regex: regex } },
//                         { bid_tx_id: { $regex: regex } },
//                         { session: { $regex: regex } },
//                         { $expr: { $regexMatch: { input: { $toString: "$points" }, regex } } },
//                         { $expr: { $regexMatch: { input: { $toString: "$winning_points" }, regex } } },
//                         { $expr: { $regexMatch: { input: { $toString: "$tx_request_number" }, regex } } },
//                         { $expr: { $regexMatch: { input: { $toString: "$digits" }, regex } } },
//                     ],

//                 }
//             });
//         }

//         const pipelineWithPagination = [
//             ...basePipeline,
//             { $sort: { [orderField]: orderDir } },
//             { $skip: skip },
//             { $limit: limit }
//         ];

//         const [results, totalArr, bid_amt, win_amt] = await Promise.all([
//             wallet_trans_history_module.aggregate(pipelineWithPagination),
//             wallet_trans_history_module.aggregate([...basePipeline, { $count: "total" }]),
//             wallet_trans_history_module.aggregate([...basePipeline2, {
//                 $group: {
//                     _id: null,
//                     total: { $sum: "$points" }
//                 }
//             }]),
//             wallet_trans_history_module.aggregate([...basePipeline, {

//                 $group: {
//                     _id: null,
//                     total: { $sum: "$winning_points" }
//                 }
//             }])
//         ]);

//         console.log("bid and win amount", bid_amt, win_amt)

//         const totalFiltered = totalArr[0]?.total || 0;

//         const sumDigitsMod10 = (str) => [...str].reduce((a, b) => a + +b, 0) % 10;

//         const data = results.map((v) => {
//             const base = {
//                 _id: v._id,
//                 user_name: v.user_name,
//                 bid_tx_id: v.bid_tx_id,
//                 game_name: v.game_name,
//                 session: v.session,
//                 pana: v.pana,
//                 points: v.points,
//                 winning_points: v.winning_points,
//                 tx_request_number: v.tx_request_number,
//                 insert_date: v.insert_date ? moment_timeZone(v.insert_date).tz('Asia/Kolkata').format('DD-MM-YYYY') : 'N/A'
//             };

//             switch (v.pana) {
//                 case 'Single Digit':
//                     return {
//                         ...base,
//                         open_digit: v.session === 'Open' ? v.digits : 'N/A',
//                         close_digit: v.session === 'Close' ? v.digits : 'N/A',
//                         open_pana: 'N/A',
//                         close_pana: 'N/A',
//                     };
//                 case 'Group Jodi':
//                 case 'Red Bracket':
//                 case 'Jodi Digit': {
//                     const padded = String(v.digits).padStart(2, '0');
//                     return {
//                         ...base,
//                         open_digit: padded[0],
//                         close_digit: padded[1],
//                         open_pana: 'N/A',
//                         close_pana: 'N/A',
//                     };
//                 }
//                 case 'Full Sangam':
//                     return {
//                         ...base,
//                         open_digit: 'N/A',
//                         close_digit: 'N/A',
//                         open_pana: v.session === 'Open' ? v.digits : 'N/A',
//                         close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
//                     };
//                 case 'Half Sangam':
//                     return {
//                         ...base,
//                         open_digit: v.session === 'Open' ? v.digits : 'N/A',
//                         close_digit: v.session === 'Close' ? v.digits : 'N/A',
//                         open_pana: v.session === 'Close' ? v.closedigits : 'N/A',
//                         close_pana: v.session === 'Open' ? v.closedigits : 'N/A',
//                     };
//                 case 'Single Pana':
//                 case 'Double Pana':
//                 case 'Triple Pana':
//                     return {
//                         ...base,
//                         open_digit: v.session === 'Open' ? sumDigitsMod10(String(v.digits)) : 'N/A',
//                         close_digit: v.session === 'Close' ? sumDigitsMod10(String(v.digits)) : 'N/A',
//                         open_pana: v.session === 'Open' ? v.digits : 'N/A',
//                         close_pana: v.session === 'Close' ? v.digits : v.closedigits,
//                     };
//                 default:
//                     return {
//                         ...base,
//                         open_digit: 'N/A',
//                         close_digit: 'N/A',
//                         open_pana: 'N/A',
//                         close_pana: 'N/A',
//                     };
//             }
//         });

//         return res.json({
//             success: true,
//             data,
//             recordsFiltered: totalFiltered,
//             total_bid_amount: bid_amt[0]?.total,
//             total_win_amount: win_amt[0]?.total,
//             limit
//         });
//     } catch (err) {
//         console.error("Error in getWinningReportDetails:", err);
//         res.status(500).json({ success: false, message: "Internal server error" });
//     }
// };

// const qrcodeImagesListGridData = async (req, res) => {
//     try {
//         const baseUrl = process?.env?.BASE_URL;
//         if (!baseUrl) {
//             return res.status(500).json({ success: false, msg: "Base URL not set" });
//         }

//         const fields = ["image_title", "display_order", "insert_date", "status"];
//         const limit = parseInt(req?.body?.length) || 10;
//         const page = parseInt(req?.body?.start) || 1;

//         const searchValue = (req?.body?.searchValue || '').trim();
//         const fieldIndex = req?.body?.fieldIndex ?? 0;
//         const orderField = fields[fieldIndex] || "insert_date";
//         const orderDir = req?.body?.order ?? -1;

//         // Build search query
//         let searchQuery = {};
//         if (searchValue) {
//             const isNumeric = !isNaN(searchValue);
//             if (isNumeric) {
//                 searchQuery = {
//                     $or: [
//                         {
//                             $expr: {
//                                 $regexMatch: {
//                                     input: { $toString: "$display_order" },
//                                     regex: `^${searchValue}`,
//                                     options: "i",
//                                 },
//                             },
//                         },
//                     ],
//                 };
//             } else {
//                 searchQuery = {
//                     $or: [
//                         { image_title: { $regex: `^${searchValue}`, $options: "i" } },
//                     ],
//                 };
//             }
//         }

//         const skip = !searchValue ? (page - 1) * limit : 0;

//         // Total filtered records
//         const totalFiltered = await qrcode_images_module.countDocuments(searchQuery);

//         // Get paginated & sorted data
//         const rawDataList = await qrcode_images_module
//             .find(searchQuery)
//             .sort({ [orderField]: orderDir })
//             .skip(skip)
//             .limit(limit)
//             .populate("qr_image")
//             .lean();

//         // Format and map the results
//         const data = rawDataList.map((doc) => {
//             const imageUrl = doc.qr_image
//                 ? `${baseUrl}/file/uploads/images/${doc.qr_image._id}`
//                 : "N/A";

//             return {
//                 ...doc,
//                 qr_image: imageUrl,
//                 insert_date:
//                     formatDateToDDMMYYYY(doc.insert_date) +
//                     " , " +
//                     get12HoursTimeFromISO(doc.insert_date),
//             };
//         });

//         // Final response
//         return res.json({
//             success: true,
//             recordsFiltered: totalFiltered,
//             limit,
//             data,
//         });
//     } catch (err) {
//         console.error("Error in qrcodeImagesListGridData:", err);
//         return res.status(500).json({ success: false, error: "Server Error" });
//     }
// };

const getWinningReportDetails = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            selected_start_date,
            selected_end_date,
        } = req.body;

        const fields = [
            "user_name", "pana", "session",
            "digits", "digits", "digits", "digits", "", "points", "tx_request_number", "winning_points", "", "bid_tx_id", "insert_date"
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        console.log("orderField-", orderField);

        let startDate = null;
        let endDate = null;

        console.log("selected_start_date", selected_start_date);

        if (selected_start_date && selected_end_date) {
            startDate = moment_timeZone
                .tz(selected_start_date.trim(), "Asia/Kolkata")
                .startOf("day")
                .toDate();

            endDate = moment_timeZone
                .tz(selected_end_date.trim(), "Asia/Kolkata")
                .endOf("day")
                .toDate();
        }

        console.log("ðŸš€ ~ getWinningReportDetails ~ startDate:", startDate);
        console.log("ðŸš€ ~ getWinningReportDetails ~ endDate:", endDate);

        // Base match conditions for ALL bids within date range
        const baseMatchConditions = {};

        // Add date filter if dates provided
        if (startDate && endDate) {
            baseMatchConditions.bid_date = { $gte: startDate, $lte: endDate };
        }

        // Main pipeline for WINNING bids data (pay_status: 1)
        const winPipeline = [
            {
                $match: {
                    ...baseMatchConditions,
                    pay_status: 1 // Only winning bids
                }
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            { $unwind: '$user' },
            {
                $project: {
                    user_name: '$user.user_name',
                    game_name: '$game_name',
                    session: '$session',
                    winning_points: '$winning_points',
                    insert_date: 1,
                    pana: '$pana',
                    digits: '$digits',
                    closedigits: '$closedigits',
                    points: '$points',
                    _id: 1,
                    bid_tx_id: '$bid_tx_id',
                    pay_status: 1
                }
            }
        ];

        // Apply search filter if search term exists
        if (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            winPipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { pana: { $regex: regex } },
                        { bid_tx_id: { $regex: regex } },
                        { session: { $regex: regex } },
                        { $expr: { $regexMatch: { input: { $toString: "$points" }, regex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$winning_points" }, regex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$digits" }, regex } } },
                    ],
                }
            });
        }

        // Pipeline for paginated results (WINNING bids only)
        const paginatedPipeline = [
            ...winPipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        // Pipeline for total count of WINNING bids
        const countPipeline = [
            ...winPipeline,
            { $count: "total" }
        ];

        // Pipeline for TOTAL BID AMOUNT (all bids - both winning and losing)
        const totalBidAmountPipeline = [
            {
                $match: baseMatchConditions // All bids within date range
            },
            {
                $group: {
                    _id: null,
                    total_bid_amount: { $sum: "$points" }
                }
            }
        ];

        // Pipeline for TOTAL WIN AMOUNT (only winning bids - pay_status: 1)
        const totalWinAmountPipeline = [
            {
                $match: {
                    ...baseMatchConditions,
                    pay_status: 1 // Only winning bids
                }
            },
            {
                $group: {
                    _id: null,
                    total_win_amount: { $sum: "$winning_points" }
                }
            }
        ];

        // Execute all queries in parallel
        const [results, totalArr, totalBidResult, totalWinResult] = await Promise.all([
            bid_history_module.aggregate(paginatedPipeline), // Winning bids for listing
            bid_history_module.aggregate(countPipeline),     // Count of winning bids
            bid_history_module.aggregate(totalBidAmountPipeline), // Total bid amount (all bids)
            bid_history_module.aggregate(totalWinAmountPipeline)  // Total win amount (winning bids only)
        ]);

        const totalFiltered = totalArr[0]?.total || 0;
        const total_bid_amount = totalBidResult[0]?.total_bid_amount || 0;
        const total_win_amount = totalWinResult[0]?.total_win_amount || 0;
        const total_profit = total_bid_amount - total_win_amount;

        console.log("Calculation Summary:", {
            total_bid_amount,
            total_win_amount,
            total_profit
        });

        // Process the results for frontend display
        const sumDigitsMod10 = (str) => {
            if (!str) return 'N/A';
            return [...String(str)].reduce((a, b) => a + parseInt(b), 0) % 10;
        };

        const data = results.map((v) => {
            const base = {
                _id: v._id,
                user_name: v.user_name,
                bid_tx_id: v.bid_tx_id,
                game_name: v.game_name,
                session: v.session,
                pana: v.pana,
                points: v.points,
                winning_points: v.winning_points,
                insert_date: v.insert_date ? moment_timeZone(v.insert_date).tz('Asia/Kolkata').format('DD-MM-YYYY HH:mm:ss') : 'N/A',
                pay_status: v.pay_status
            };

            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...base,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
                case 'Group Jodi':
                case 'Red Bracket':
                case 'Jodi Digit': {
                    const padded = String(v.digits).padStart(2, '0');
                    return {
                        ...base,
                        open_digit: padded[0],
                        close_digit: padded[1],
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
                }
                case 'Full Sangam':
                    return {
                        ...base,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                    };
                case 'Half Sangam':
                    return {
                        ...base,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                        open_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                        close_pana: v.session === 'Open' ? v.closedigits : 'N/A',
                    };
                case 'Single Pana':
                case 'Double Pana':
                case 'Triple Pana':
                    return {
                        ...base,
                        open_digit: v.session === 'Open' ? sumDigitsMod10(String(v.digits)) : 'N/A',
                        close_digit: v.session === 'Close' ? sumDigitsMod10(String(v.digits)) : 'N/A',
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.digits : v.closedigits,
                    };
                default:
                    return {
                        ...base,
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
            }
        });

        return res.json({
            success: true,
            data,
            recordsFiltered: totalFiltered,
            total_bid_amount,
            total_win_amount,
            total_profit,
            limit
        });
    } catch (err) {
        console.error("Error in getWinningReportDetails:", err);
        res.status(500).json({ success: false, message: "Internal server error" });
    }
};


// const getWinningReportDetails = async (req, res) => {
//     try {
//         const {
//             length = 10,
//             start = 1,
//             fieldIndex = 0,
//             order = -1,
//             searchValue = "",
//             selected_start_date,
//             selected_end_date,
//         } = req.body;

//         const fields = [
//             "user_name", "pana", "session",
//             "digits", "digits", "digits", "digits", "", "points", "tx_request_number", "winning_points", "", "bid_tx_id", "insert_date"
//         ];

//         const limit = parseInt(length);
//         const page = parseInt(start);
//         const skip = !searchValue && page !== 0 ? (page - 1) : 0;
//         const orderField = fields[fieldIndex] || "insert_date";
//         const orderDir = parseInt(order);
//         const searchTerm = searchValue.trim();

//         console.log("orderField-", orderField);

//         let startDate = null;
//         let endDate = null;

//         console.log("selected_start_date", selected_start_date);

//         if (selected_start_date && selected_end_date) {
//             startDate = moment_timeZone
//                 .tz(selected_start_date.trim(), "Asia/Kolkata")
//                 .startOf("day")
//                 .toDate();

//             endDate = moment_timeZone
//                 .tz(selected_end_date.trim(), "Asia/Kolkata")
//                 .endOf("day")
//                 .toDate();
//         }

//         console.log("ðŸš€ ~ getWinningReportDetails ~ startDate:", startDate);
//         console.log("ðŸš€ ~ getWinningReportDetails ~ endDate:", endDate);

//         // Find game results within date range
//         let gameResults = [];

//         if (startDate && endDate) {
//             gameResults = await game_result_history_module.find({
//                 result_date: { $gte: startDate, $lte: endDate }
//             }).lean();
//         } else {
//             gameResults = await game_result_history_module.find({}).lean();
//         }

//         if (!gameResults || gameResults.length === 0) {
//             return res.json({ 
//                 success: true, 
//                 data: [], 
//                 recordsFiltered: 0,
//                 total_bid_amount: 0,
//                 total_win_amount: 0 
//             });
//         }

//         // Extract all result tokens from multiple game results
//         const resultTokens = [];
//         gameResults.forEach(result => {
//             if (result.open_result_token) resultTokens.push(result.open_result_token);
//             if (result.close_result_token) resultTokens.push(result.close_result_token);
//         });

//         if (resultTokens.length === 0) {
//             return res.json({ 
//                 success: true, 
//                 data: [], 
//                 recordsFiltered: 0,
//                 total_bid_amount: 0,
//                 total_win_amount: 0 
//             });
//         }

//         // Base match conditions for wallet transactions
//         const baseMatchConditions = {
//             $or: [
//                 { open_result_token: { $in: resultTokens } },
//                 { close_result_token: { $in: resultTokens } }
//             ]
//         };

//         if (startDate && endDate) {
//             baseMatchConditions.insert_date = { $gte: startDate, $lte: endDate };
//         }

//         // Pipeline for winning data (amount_status: 8)
//         const winPipeline = [
//             { 
//                 $match: {
//                     ...baseMatchConditions,
//                     amount_status: 8 // Winning amount
//                 }
//             },
//             {
//                 $lookup: {
//                     from: 'bid_histories',
//                     localField: 'bid_tx_id',
//                     foreignField: 'bid_tx_id',
//                     as: 'bid'
//                 }
//             },
//             { $unwind: '$bid' },
//             {
//                 $lookup: {
//                     from: 'users',
//                     localField: 'bid.userDB_id',
//                     foreignField: '_id',
//                     as: 'user'
//                 }
//             },
//             { $unwind: '$user' },
//             {
//                 $project: {
//                     user_name: '$user.user_name',
//                     game_name: '$bid.game_name',
//                     session: '$bid.session',
//                     winning_points: '$bid.winning_points',
//                     tx_request_number: 1,
//                     insert_date: 1,
//                     pana: '$bid.pana',
//                     digits: '$bid.digits',
//                     closedigits: '$bid.closedigits',
//                     points: '$bid.points',
//                     _id: 1,
//                     bid_tx_id: '$bid.bid_tx_id',
//                     amount: 1
//                 }
//             }
//         ];

//         // Pipeline for bid amount calculation (amount_status: 5)
//         const bidAmountPipeline = [
//             { 
//                 $match: {
//                     ...baseMatchConditions,
//                     amount_status: 5 // Bid placed amount
//                 }
//             },
//             {
//                 $group: {
//                     _id: null,
//                     total_bid_amount: { $sum: "$amount" }
//                 }
//             }
//         ];

//         // Pipeline for win amount calculation (amount_status: 8)
//         const winAmountPipeline = [
//             { 
//                 $match: {
//                     ...baseMatchConditions,
//                     amount_status: 8 // Winning amount
//                 }
//             },
//             {
//                 $group: {
//                     _id: null,
//                     total_win_amount: { $sum: "$amount" }
//                 }
//             }
//         ];

//         // Apply search filter if search term exists
//         if (searchTerm) {
//             const regex = new RegExp(`^${searchTerm}`, "i");
//             winPipeline.push({
//                 $match: {
//                     $or: [
//                         { user_name: { $regex: regex } },
//                         { pana: { $regex: regex } },
//                         { bid_tx_id: { $regex: regex } },
//                         { session: { $regex: regex } },
//                         { $expr: { $regexMatch: { input: { $toString: "$points" }, regex } } },
//                         { $expr: { $regexMatch: { input: { $toString: "$winning_points" }, regex } } },
//                         { $expr: { $regexMatch: { input: { $toString: "$tx_request_number" }, regex } } },
//                         { $expr: { $regexMatch: { input: { $toString: "$digits" }, regex } } },
//                     ],
//                 }
//             });
//         }

//         // Pipeline for paginated results
//         const paginatedPipeline = [
//             ...winPipeline,
//             { $sort: { [orderField]: orderDir } },
//             { $skip: skip },
//             { $limit: limit }
//         ];

//         // Pipeline for total count
//         const countPipeline = [
//             ...winPipeline,
//             { $count: "total" }
//         ];

//         // Execute all queries in parallel
//         const [results, totalArr, bidAmountResult, winAmountResult] = await Promise.all([
//             wallet_trans_history_module.aggregate(paginatedPipeline),
//             wallet_trans_history_module.aggregate(countPipeline),
//             wallet_trans_history_module.aggregate(bidAmountPipeline),
//             wallet_trans_history_module.aggregate(winAmountPipeline)
//         ]);

//         const totalFiltered = totalArr[0]?.total || 0;
//         const total_bid_amount = bidAmountResult[0]?.total_bid_amount || 0;
//         const total_win_amount = winAmountResult[0]?.total_win_amount || 0;

//         console.log("Bid and Win amounts:", { total_bid_amount, total_win_amount });

//         // Process the results for frontend display
//         const sumDigitsMod10 = (str) => {
//             if (!str) return 'N/A';
//             return [...String(str)].reduce((a, b) => a + parseInt(b), 0) % 10;
//         };

//         const data = results.map((v) => {
//             const base = {
//                 _id: v._id,
//                 user_name: v.user_name,
//                 bid_tx_id: v.bid_tx_id,
//                 game_name: v.game_name,
//                 session: v.session,
//                 pana: v.pana,
//                 points: v.points,
//                 winning_points: v.winning_points,
//                 tx_request_number: v.tx_request_number,
//                 insert_date: v.insert_date ? moment_timeZone(v.insert_date).tz('Asia/Kolkata').format('DD-MM-YYYY') : 'N/A'
//             };

//             switch (v.pana) {
//                 case 'Single Digit':
//                     return {
//                         ...base,
//                         open_digit: v.session === 'Open' ? v.digits : 'N/A',
//                         close_digit: v.session === 'Close' ? v.digits : 'N/A',
//                         open_pana: 'N/A',
//                         close_pana: 'N/A',
//                     };
//                 case 'Group Jodi':
//                 case 'Red Bracket':
//                 case 'Jodi Digit': {
//                     const padded = String(v.digits).padStart(2, '0');
//                     return {
//                         ...base,
//                         open_digit: padded[0],
//                         close_digit: padded[1],
//                         open_pana: 'N/A',
//                         close_pana: 'N/A',
//                     };
//                 }
//                 case 'Full Sangam':
//                     return {
//                         ...base,
//                         open_digit: 'N/A',
//                         close_digit: 'N/A',
//                         open_pana: v.session === 'Open' ? v.digits : 'N/A',
//                         close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
//                     };
//                 case 'Half Sangam':
//                     return {
//                         ...base,
//                         open_digit: v.session === 'Open' ? v.digits : 'N/A',
//                         close_digit: v.session === 'Close' ? v.digits : 'N/A',
//                         open_pana: v.session === 'Close' ? v.closedigits : 'N/A',
//                         close_pana: v.session === 'Open' ? v.closedigits : 'N/A',
//                     };
//                 case 'Single Pana':
//                 case 'Double Pana':
//                 case 'Triple Pana':
//                     return {
//                         ...base,
//                         open_digit: v.session === 'Open' ? sumDigitsMod10(String(v.digits)) : 'N/A',
//                         close_digit: v.session === 'Close' ? sumDigitsMod10(String(v.digits)) : 'N/A',
//                         open_pana: v.session === 'Open' ? v.digits : 'N/A',
//                         close_pana: v.session === 'Close' ? v.digits : v.closedigits,
//                     };
//                 default:
//                     return {
//                         ...base,
//                         open_digit: 'N/A',
//                         close_digit: 'N/A',
//                         open_pana: 'N/A',
//                         close_pana: 'N/A',
//                     };
//             }
//         });

//         return res.json({
//             success: true,
//             data,
//             recordsFiltered: totalFiltered,
//             total_bid_amount,
//             total_win_amount,
//             limit
//         });
//     } catch (err) {
//         console.error("Error in getWinningReportDetails:", err);
//         res.status(500).json({ success: false, message: "Internal server error" });
//     }
// };

const qrcodeImagesListGridData = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;

        const qrList = await qrcode_images_module.find().sort({ insert_date: -1 }).limit(1).lean();

        // Attach full image URL
        const result = qrList.map(qr => ({
            ...qr,
            qr_image: `${baseUrl}/uploads/qrcode-images/${qr.qr_image}`
        }));

        res.status(200).json({
            success: true,
            data: result
        });
    } catch (err) {
        console.error("Get QR Images Error:", err);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error",
        });
    }
};

const deleteQrcodeImage = async (req, res) => {
    try {
        const { imageDB_id = "" } = req?.body || {};

        if (!imageDB_id) {
            return res.status(400).json({ success: false, msg: 'Missing required fields' });
        }

        if (!mongoose.isValidObjectId(imageDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid how_to_playDB_id.",
            });
        }

        const image = await qrcode_images_module.findOne({ _id: imageDB_id });

        if (!image) {
            return res.json({
                success: false,
                msg: 'Image not found'
            });
        }

        await file_module.findByIdAndDelete(image?.slider_image)

        await qrcode_images_module.findByIdAndDelete(imageDB_id);

        res.json({
            success: true,
            msg: 'Image Successfully Deleted'
        });

    } catch (err) {
        res.status(500).json({
            success: false,
            msg: 'Internal Server Error'
        });
    }
};

// const addQrcodeImage = async (req, res) => {
//     try {

//         console.log(`(((((((()))))) ~ adminController.js:10965 ~ addQrcodeImage ~ req.file:`, req.file);
//         const baseUrl = process?.env?.BASE_URL;
//         if (!baseUrl) {
//             return res.status(500).json({ success: false, msg: "Base URL not set" });
//         }

//         const { display_order = "" } = req.body || {};

//         // Validate display order
//         // if (!display_order || isNaN(display_order)) {
//         //     return res.status(400).json({ success: false, msg: "Display order is required and must be a number." });
//         // }

//         // Check if image file is provided
//         if (!req.file || !req.file.buffer || !req.file.mimetype) {
//             return res.status(400).json({ success: false, msg: "Valid image file is required." });
//         }

//         // Check for duplicate display order
//         const isDisplayOrderExist = await qrcode_images_module.findOne({ display_order });
//         if (isDisplayOrderExist) {
//             return res.status(409).json({ success: false, msg: `Display order "${display_order}" already exists.` });
//         }

//         // Save image in DB
//         const image = new file_module({
//             fileInfo: {
//                 fileBuffer: req.file.buffer,
//                 content_type: req.file.mimetype,
//             },
//         });
//         const savedImage = await image.save();

//         let qrData = new qrcode_images_module({
//             qr_image: savedImage._id,
//             display_order: parseInt(display_order),
//         });

//         qrData = await qrData.save();
//         const leanQrData = qrData.toObject();

//         const imageUrl = leanQrData.qr_image
//             ? `${baseUrl}/file/uploads/images/${leanQrData.qr_image}`
//             : "N/A";

//         qrData = {
//             ...leanQrData,
//             qr_image: imageUrl,
//             insert_date:
//                 formatDateToDDMMYYYY(leanQrData.insert_date) +
//                 " , " +
//                 get12HoursTimeFromISO(leanQrData.insert_date),
//         }

//         res.status(200).json({
//             success: true,
//             msg: "Qr image successfully added.",
//             qrData
//         });
//     } catch (err) {
//         console.error("Add QR Image Error:", err);
//         res.status(500).json({
//             success: false,
//             msg: "Internal Server Error",
//         });
//     }
// };


const addQrcodeImage = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const { image_title = "" } = req.body || {};

        if (!req.file) {
            return res.status(400).json({ success: false, msg: "Valid image file is required." });
        }

        // Save record in DB
        let qrData = new qrcode_images_module({
            image_title,
            qr_image: req.file.filename, // save only filename
        });

        qrData = await qrData.save();
        const leanQrData = qrData.toObject();

        // Build public image URL
        const imageUrl = `${baseUrl}/uploads/qrcode-images/${leanQrData.qr_image}`;

        res.status(200).json({
            success: true,
            msg: "QR image successfully added.",
            qrData: {
                ...leanQrData,
                qr_image: imageUrl, // send full URL
            }
        });
    } catch (err) {
        console.error("Add QR Image Error:", err);
        res.status(500).json({
            success: false,
            msg: "Internal Server Error code",
        });
    }
};



// incomplete function
const forgotPassword = async (req, res) => {
    try {
        const email = req?.body?.email?.trim() || '';

        if (!email) {
            return res.json({
                success: false,
                msg: "Please enter your email"
            });
        }

        const user = await admin_module.findOne({ admin_email: email });

        if (!user) {
            return res.json({
                success: false,
                msg: "Email is not found"
            });
        }

        const username = user.username;
        const password = bcrypt.compare(user.password);

        // only return password true or false meaning if password is correct or not

        const subject = 'Password Recovery';
        const msg = `
      <p>Hello <strong>Admin, </strong></p>
      <p style="margin:5px 0;">Admin Panel received a password recovery request. <br />
      If you request this, please check your login details below.</p>
      <p>User Name - <strong>${username}</strong></p>
      <p>Password - <strong>${password}</strong></p>
      <br />
      <p>If you did not request this recovery, just ignore and delete this mail. Your account is always safe.</p>`;

        // Configure your SMTP settings here
        const transporter = nodemailer.createTransport({
            host: 'smtp.example.com',
            port: 587,
            secure: false, // true for 465, false for other ports
            auth: {
                user: 'your@email.com',
                pass: 'yourpassword'
            }
        });

        const mailOptions = {
            from: '"Admin Panel" <your@email.com>',
            to: email,
            subject: subject,
            html: msg
        };

        await transporter.sendMail(mailOptions);

        return res.json({
            status: 'success',
            msg: "Password successfully sent to your email. Please check your Inbox/Spam/Junk Emails."
        });

    } catch (error) {
        console.error(error);
        return res.status(500).json({
            status: "error",
            msg: "Something went wrong. Please try again."
        });
    }
};

const updatePassword = async (req, res) => {
    try {
        const { oldpass = "", newpass = "", retypepass = "" } = req.body || {};

        console.log(`(((((((()))))) ~ adminController.js:11227 ~ updatePassword ~ eq.body:`, req.admin);

        if (!oldpass || !newpass || !retypepass) {
            return res.status(400).json({ success: false, msg: 'All fields are required' });
        }

        if (newpass !== retypepass) {
            return res.status(400).json({ success: false, msg: 'Passwords do not match' });
        }

        if (newpass.length < 8) {
            return res.status(400).json({ success: false, msg: 'Password must be at least 8 characters long' });
        }

        const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/;
        if (!passwordRegex.test(newpass)) {
            return res.status(400).json({
                success: false,
                msg: 'Password must include uppercase, lowercase, number, and special character'
            });
        }

        const adminData = req.admin || null;
        if (!adminData || !adminData._id) {
            return res.status(401).json({ success: false, msg: 'User not found' });
        }

        const admin = await admin_module.findById(adminData._id);

        console.log(`(((((((()))))) ~ adminController.js:11254 ~ updatePassword ~ admin:`, admin);
        if (!admin) {
            return res.status(404).json({ success: false, msg: 'User details not found' });
        }

        const isMatched = await bcrypt.compare(oldpass, admin.password);
        if (!isMatched) {
            return res.status(400).json({ success: false, msg: 'Old password is incorrect' });
        }

        const hashedPassword = await bcrypt.hash(newpass, 10);
        await admin_module.updateOne({ _id: adminData._id }, { $set: { password: hashedPassword } });

        return res.json({ success: true, msg: 'Password updated successfully' });

    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: 'Something went wrong' });
    }
};

const marketOpenCloseFunction = async (req, res) => {
    try {
        const {
            DB_id = "",
            collectionName = "",
            document_fieldName = "",
            status_name = ""
        } = req?.body || {};

        if (!DB_id || !collectionName || !document_fieldName || !status_name) {
            return res.status(400).json({ success: false, msg: "Missing required fields" });
        }

        if (!mongoose.isValidObjectId(DB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid ID format" });
        }

        let Model;
        try {
            Model = mongoose.model(collectionName);
        } catch (err) {
            return res.status(400).json({ success: false, msg: "Invalid collection name" });
        }

        const query = { [document_fieldName]: DB_id };
        const record = await Model.findOne(query);

        if (!record) {
            return res.status(404).json({ success: false, msg: "Market record not found" });
        }

        const currentStatus = record[status_name];
        const newStatus = (currentStatus === 1 || currentStatus === '1') ? 0 : 1;
        const msg = newStatus === 1
            ? "Market Successfully Open For Today"
            : "Market Successfully Close For Today";

        record[status_name] = newStatus;
        await record.save();

        return res.json({ success: true, msg });
    } catch (err) {
        console.error("marketOpenCloseFunction error:", err);
        return res.status(500).json({ success: false, msg: "Server error" });
    }
};

const acceptFundRequest = async (req, res) => {
    try {
        const fund_requestDB_id = (req?.body?.fund_requestDB_id || '').trim();

        if (!fund_requestDB_id) {
            return res.json({ success: false, msg: "Fund request ID is required" });
        }

        if (!mongoose.isValidObjectId(fund_requestDB_id)) {
            return res.json({ success: false, msg: "Invalid Fund Request ID" });
        }

        const fundRequest = await add_fund_request_module.findById(fund_requestDB_id);

        if (!fundRequest) return res.json({ success: false, msg: "Request not found" });

        const { userDB_id, request_amount: amount, request_status: status, request_number } = fundRequest;

        if (status !== 0) {
            return res.json({
                success: false,
                msg: "Request already processed or invalid3333333333333"
            });
        }

        const user = await user_module.findById(userDB_id);
        if (!user) return res.json({ success: false, msg: "User not found" });

        user.wallet_balance += amount;
        await user.save();

        fundRequest.request_status = 2; // Mark accepted
        await fundRequest.save();

        const hasTransaction = await wallet_trans_history_module.exists({
            userDB_id,
            amount_status: { $in: [1, 19] }
        });

        if (!hasTransaction) {
            const referEntry = await refer_details_module.findOne({ refer_to: userDB_id });
            if (referEntry) {
                const referByUser = await user_module.findById(referEntry.refer_by);
                const settings = await fix_values_module.findOne();

                if (referByUser && settings) {
                    const bonusPercent = referByUser.is_agent ? settings.agent_refer_bonus : settings.user_refer_bonus;
                    const bonus = (amount * bonusPercent) / 100;

                    referByUser.wallet_balance += bonus;
                    await referByUser.save();

                    await refer_details_module.updateOne(
                        { refer_to: userDB_id, refer_by: referEntry.refer_by },
                        { $inc: { bonus } }
                    );

                    const bonusTxn = new wallet_trans_history_module({
                        userDB_id: referByUser._id,
                        amount: bonus,
                        transaction_type: 1,
                        transaction_note: 'User Refer Bonus',
                        amount_status: 6,
                        tx_request_number: getUserRandomToken(),
                    });
                    await bonusTxn.save();
                }
            }
        }

        const txn = new wallet_trans_history_module({
            userDB_id,
            amount,
            transaction_type: 1,
            transaction_note: `Request No.${request_number} Processed`,
            amount_status: 1,
            tx_request_number: request_number,
        });
        await txn.save();

        const notification = new user_notification_module({
            userDB_id,
            msg: `Congratulations, Your fund request of amount ${amount} is accepted.`,
        });
        await notification.save();

        const playerRecords = await player_ids_module.find({ userDB_id });
        const player_ids = playerRecords.map(p => p.playerDB_id).join(',');

        if (player_ids) {
            // sendNotification(
            //     player_ids,
            //     `Request No.${request_number} For Points Processed`,
            //     `Congratulations, Your point add request of points ${amount} is accepted.`,
            //     '',
            //     '2'
            // );
        }

        return res.json({
            success: true,
            request_status: "Accepted",
            msg: "Request Successfully Accepted"
        });

    } catch (err) {
        console.error(err);
        return res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
};

const creditTransactionTableGridData = async (req, res) => {
    try {
        const columns = [
            '_id',
            'amount',
            'transaction_note',
            'transfer_note',
            'insert_date',
            'tx_request_number',
        ];

        const userDB_id = req?.body?.userDB_id?.trim?.();
        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const orderColIndex = parseInt(req?.body?.order?.[0]?.column) || 0;
        const order = columns[orderColIndex] || 'insert_date';
        const dir = req?.body?.order?.[0]?.dir === 'desc' ? -1 : 1;
        const searchValue = req?.body?.search?.value?.trim() || '';

        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'User ID is required' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid User ID' });
        }

        const baseFilter = {
            userDB_id,
            transaction_type: 1,
        };

        const filter = { ...baseFilter };

        if (searchValue) {
            filter.$or = [
                { transaction_note: { $regex: searchValue, $options: 'i' } },
                { transfer_note: { $regex: searchValue, $options: 'i' } },
                { tx_request_number: { $regex: searchValue, $options: 'i' } },
                { amount: { $regex: searchValue, $options: 'i' } },
            ];
        }

        const [totalData, totalFiltered, tb_data] = await Promise.all([
            wallet_trans_history_module.countDocuments(baseFilter),
            wallet_trans_history_module.countDocuments(filter),
            wallet_trans_history_module.find(filter)
                .sort({ [order]: dir })
                .skip(start)
                .limit(limit)
                .lean()
        ]);

        const data = tb_data.map((rs) => {
            const amount = `+ ${rs.amount} â‚¹`;
            return {
                amount,
                tx_note: rs.transaction_note || '',
                transfer_note: rs.transfer_note || 'N/A',
                insert_date: new Date(rs.insert_date).toLocaleString('en-GB', {
                    day: '2-digit',
                    month: 'short',
                    year: 'numeric',
                    hour: '2-digit',
                    minute: '2-digit',
                    second: '2-digit',
                }),
                tx_req_no: rs.tx_request_number || 'N/A',
            };
        });

        return res.json({
            success: true,
            draw: parseInt(req.body.draw) || 1,
            recordsTotal: totalData,
            recordsFiltered: totalFiltered,
            data,
        });
    } catch (err) {
        console.error('creditTransactionTableGridData Error:', err);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const debitTransactionTableGridData = async (req, res) => {
    try {
        const columns = [
            '_id',
            'amount',
            'transaction_note',
            'transfer_note',
            'insert_date',
            'tx_request_number',
        ];

        const userDB_id = (req?.body?.userDB_id || '').trim();
        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const orderColumnIndex = parseInt(req?.body?.order?.[0]?.column) || 0;
        const orderColumn = columns[orderColumnIndex] || 'insert_date';
        const orderDir = req?.body?.order?.[0]?.dir === 'asc' ? 1 : -1;
        const searchValue = (req?.body?.search?.value || '').trim();
        const draw = parseInt(req?.body?.draw) || 1;

        // Validate userDB_id
        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'User ID is required.' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid User ID.' });
        }

        const baseQuery = {
            userDB_id,
            transaction_type: 2, // Debit
        };

        let searchQuery = {};

        if (searchValue) {
            const regex = new RegExp(searchValue, 'i');
            searchQuery = {
                $or: [
                    { transaction_note: { $regex: regex } },
                    { transfer_note: { $regex: regex } },
                    { tx_request_number: { $regex: regex } },
                ]
            };
        }

        const finalQuery = { ...baseQuery, ...searchQuery };

        const [totalData, totalFiltered, transactions] = await Promise.all([
            wallet_trans_history_module.countDocuments(baseQuery),
            wallet_trans_history_module.countDocuments(finalQuery),
            wallet_trans_history_module
                .find(finalQuery)
                .sort({ [orderColumn]: orderDir })
                .skip(start)
                .limit(limit)
                .lean()
        ]);

        const data = transactions.map((tx) => ({
            amount: `- ${tx.amount} â‚¹`,
            tx_note: tx.transaction_note || '',
            transfer_note: tx.transfer_note || 'N/A',
            insert_date: new Date(tx.insert_date).toLocaleString('en-GB', {
                day: '2-digit',
                month: 'short',
                year: 'numeric',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit',
            }),
            tx_req_no: tx.tx_request_number || 'N/A',
        }));

        res.json({
            success: true,
            draw,
            recordsTotal: totalData,
            recordsFiltered: totalFiltered,
            data,
        });

    } catch (error) {
        console.error('debitTransactionTableGridData Error:', error);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const userBidHistoryTableGridData = async (req, res) => {
    try {
        const columns = [
            '_id',
            'game_name',
            'pana',
            'session',
            'digits',
            'closedigits',
            'points',
            'insert_date',
        ];

        const userDB_id = (req?.body?.userDB_id || '').trim();
        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const orderColumnIndex = parseInt(req?.body?.order?.[0]?.column) || 0;
        const orderColumn = columns[orderColumnIndex] || 'insert_date';
        const orderDir = req?.body?.order?.[0]?.dir === 'asc' ? 1 : -1;
        const searchValue = (req?.body?.search?.value || '').trim();
        const draw = parseInt(req?.body?.draw) || 1;

        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'User ID is required.' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid User ID.' });
        }

        const baseQuery = { userDB_id };
        let searchQuery = {};

        if (searchValue) {
            const regex = new RegExp(searchValue, 'i');
            searchQuery = {
                $or: [
                    { game_name: { $regex: regex } },
                    { pana: { $regex: regex } },
                    { session: { $regex: regex } },
                    { digits: { $regex: regex } },
                    { closedigits: { $regex: regex } },
                ]
            };
        }

        const finalQuery = { ...baseQuery, ...searchQuery };

        const [totalData, totalFiltered, bids] = await Promise.all([
            bid_history_module.countDocuments(baseQuery),
            searchValue ? bid_history_module.countDocuments(finalQuery) : bid_history_module.countDocuments(baseQuery),
            bid_history_module
                .find(finalQuery)
                .sort({ [orderColumn]: orderDir })
                .skip(start)
                .limit(limit)
                .lean()
        ]);

        const data = bids.map((bid) => ({
            game_name: bid.game_name,
            game_type: bid.pana,
            session: bid.session,
            digits: bid.digits,
            close_digits: bid.closedigits,
            points: bid.points,
            insert_date: new Date(bid.insert_date).toLocaleString('en-GB', {
                day: '2-digit',
                month: 'short',
                year: 'numeric',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit',
            }),
        }));

        res.json({
            success: true,
            draw,
            recordsTotal: totalData,
            recordsFiltered: totalFiltered,
            data,
        });

    } catch (error) {
        console.error('userBidHistoryTableGridData Error:', error);
        res.status(500).json({ success: false, msg: 'Server error' });
    }
};

const userWinningHistoryData = async (req, res) => {
    try {
        const { result_date = '', userDB_id = '' } = req.body || {};

        if (!result_date || !userDB_id) {
            return res.status(400).json({ success: false, msg: 'Missing result_date or userDB_id' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid userDB_id' });
        }

        const date = new Date(result_date);
        if (isNaN(date.getTime())) {
            return res.status(400).json({ success: false, msg: 'Invalid result_date' });
        }

        const startOfDay = new Date(date.setHours(0, 0, 0, 0));
        const endOfDay = new Date(date.setHours(23, 59, 59, 999));

        const query = {
            userDB_id,
            amount_status: 8,
            insert_date: { $gte: startOfDay, $lte: endOfDay },
        };

        const projection = {
            amount: 1,
            transaction_note: 1,
            tx_request_number: 1,
            insert_date: 1,
            _id: 0,
        };

        const results = await wallet_trans_history_module
            .find(query, projection)
            .sort({ transaction_id: 1 })
            .lean();

        const formattedResults = results.map((item) => ({
            amount: item.amount,
            transaction_note: item.transaction_note,
            tx_request_number: item.tx_request_number,
            insert_date: new Date(item.insert_date).toLocaleString('en-GB', {
                day: '2-digit',
                month: 'short',
                year: 'numeric',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit',
            }),
        }));

        res.json({ success: true, data: formattedResults });
    } catch (error) {
        console.error('userWinningHistoryData Error:', error);
        res.status(500).json({ success: false, msg: 'Server error' });
    }
};

const allowedBetting = async (req, res) => {
    try {
        const userDB_id = (req?.body?.userDB_id || {}).trim();

        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'userDB_id is required' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid userDB_id' });
        }

        const result = await user_module.updateOne(
            { _id: userDB_id },
            { $set: { betting_status: 1 } }
        );

        if (result.modifiedCount === 0) {
            return res.status(404).json({ success: false, msg: 'User not found or betting status already allowed' });
        }

        res.json({ success: true, msg: 'Betting allowed for the user.' });

    } catch (error) {
        console.error('Error in allowedBetting:', error);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const changeLogoutStatus = async (req, res) => {
    try {
        const userDB_id = (req?.body?.userDB_id || '').trim();

        if (!userDB_id) {
            return res.status(400).json({ success: false, msg: 'userDB_id is required' });
        }

        if (!mongoose.isValidObjectId(userDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid userDB_id' });
        }

        const filter = { userDB_id };
        const update = { $set: { logout_status: 1 } };

        const result = await user_device_record_module.updateOne(filter, update);

        if (result.modifiedCount === 0) {
            return res.status(404).json({ success: false, msg: 'User device record not found or already logged out' });
        }

        res.json({ success: true, msg: 'Logout status updated successfully', logout_status: 1 });
    } catch (error) {
        console.error('Error in changeLogoutStatus:', error);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const addMaster = async (req, res) => {
    try {
        let {
            adminDB_id = "",
            sub_admin_name = "",
            email = "",
            user_name = "",
            password = ""
        } = req?.body || {};

        adminDB_id = toStr(adminDB_id)
        sub_admin_name = toStr(sub_admin_name)
        email = toStr(email)
        user_name = toStr(user_name)
        password = toStr(password)

        if (!sub_admin_name || !email || !user_name || !password || !adminDB_id) {
            return res.status(400).json({ success: false, msg: 'All fields are required' });
        }

        const existing = await admin_module.findOne({ username: user_name });
        if (existing) {
            return res.json({
                success: false,
                msg: 'Username is already registered'
            });
        }

        const encryptedPassword = await bcrypt.hash(password, 10);

        const userdata = {
            full_name: capitalizeWords(sub_admin_name),
            admin_email: email,
            username: user_name,
            password: encryptedPassword,
            admin_type: 3,
        };

        if (adminDB_id === '') {
            await admin_module.create(userdata);
            return res.json({
                success: true,
                msg: 'Master successfully added'
            });
        } else {
            await admin_module.updateOne({ _id: adminDB_id }, { $set: userdata });
            return res.json({
                success: true,
                msg: 'Master updated successfully.'
            });
        }
    } catch (error) {
        console.error('Error in addMaster:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const fundRequestListGridData = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }
        const columns = [
            '_id',
            'userDB_id',
            'request_amount',
            'request_number',
            'fund_payment_receipt',
            'insert_date',
            'request_status',
        ];

        const limit = Number(toStr(req?.body?.length)) || 10;
        const start = Number(toStr(req?.body?.start)) || 0;

        const orderColumnIndex = Number(toStr(req?.body?.order?.[0]?.column));
        const orderField = columns[orderColumnIndex] || '_id';
        const orderDir = req.body.order?.[0]?.dir === 'desc' ? -1 : 1;

        const searchValue = (req?.body?.search?.value || '').trim();

        let matchStage = {};
        if (searchValue) {
            const regex = new RegExp(searchValue, 'i');
            matchStage = {
                $or: [
                    { 'userData.user_name': regex },
                    { request_amount: regex },
                    { request_number: regex },
                ]
            };
        }

        const aggregatePipeline = [
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            { $unwind: '$userData' },
            { $match: matchStage },
            {
                $project: {
                    request_amount: 1,
                    request_number: 1,
                    fund_payment_receipt: 1,
                    request_status: 1,
                    userDB_id: 1,
                    insert_date: { $dateToString: { format: '%d %b %Y', date: '$insert_date' } },
                    'userData.user_name': 1
                }
            },
            { $sort: { [orderField]: orderDir } },
            { $skip: start },
            { $limit: limit }
        ];

        const totalRecords = await add_fund_request_module.countDocuments();
        // console.log(`Total Records: ${totalRecords}`);

        const filteredRecordsResult = await add_fund_request_module.aggregate([
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            { $unwind: '$userData' },
            { $match: matchStage },
            { $count: 'count' }
        ]);
        const filteredRecords = filteredRecordsResult[0]?.count || 0;

        const data = await add_fund_request_module.aggregate(aggregatePipeline);

        const responseData = data.map(item => {
            let receipt_img = 'N/A';
            if (item.fund_payment_receipt) {
                const fileUrl = `${baseUrl}/file/uploads/images/${item?.fund_payment_receipt?.toString()}`;
                receipt_img = `<li><a class="item" href="${baseUrl}"><img class="icons" src="${fileUrl}"></a></li>`;
            }

            let display_status = '';
            switch (item.request_status) {
                case 0:
                    display_status = `<badge class="badge badge-info">Pending</badge>`;
                    break;
                case 1:
                    display_status = `<badge class="badge badge-danger">Rejected</badge>`;
                    break;
                default:
                    display_status = `<badge class="badge badge-success">Accepted</badge>`;
                    break;
            }

            return {
                user_name: `<a href="${baseUrl}/admin/view-user/${item.userDB_id}">${item.userData.user_name}</a>`,
                request_amount: `&#x20b9;${item.request_amount}`,
                request_number: item.request_number,
                receipt_img,
                insert_date: item.insert_date,
                request_status: item.request_status,
                fund_request_id: item.fund_request_id,
                display_status
            };
        });

        res.json({
            success: true,
            draw: Number.parseInt(req.body.draw, 10) || 0,
            recordsTotal: totalRecords,
            recordsFiltered: filteredRecords,
            data: responseData
        });
    } catch (err) {
        console.error('Error in fundRequestListGridData:', err);
        res.status(500).json({
            success: false,
            msg: 'Internal server error'
        });
    }
};

const withdrawRequestListGridData = async (req, res) => {
    try {
        const columns = [
            '_id',
            'user_name',
            'mobile',
            'request_amount',
            'request_number',
            'insert_date',
            'request_status',
            '_id',
            '_id'
        ];

        if (!process.env.BASE_URL) {
            return res.status(400).json({ success: false, msg: 'Base URL not set' });
        }

        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const orderIndex = req?.body?.order ? parseInt(req?.body?.order[0]?.column) : 0;
        const orderColumn = columns[orderIndex] || '_id';
        const orderDir = req?.body?.order ? req?.body?.order[0]?.dir : 'asc';

        const searchValue = req?.body?.search ? req?.body?.search?.value : '';

        let match = {};

        if (searchValue && searchValue.trim() !== '') {
            const regex = new RegExp('^' + searchValue, 'i');
            match = {
                $or: [
                    { 'userData.user_name': { $regex: regex } },
                    { 'userData.mobile': { $regex: regex } },
                    { request_amount: { $regex: regex } },
                    { request_number: { $regex: regex } },
                ]
            };
        }

        const pipeline = [
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            { $unwind: '$userData' },
            { $match: match },
            {
                $addFields: {
                    insert_date_formatted: {
                        $dateToString: {
                            format: '%d %b %Y %H:%M:%S',
                            date: '$insert_date',
                            timezone: 'Asia/Kolkata'
                        }
                    }
                }
            }
        ];

        const totalData = await withdraw_fund_request_module.countDocuments();

        const totalFiltered = searchValue ? await withdraw_fund_request_module.aggregate(pipeline.concat([{ $count: "count" }])) : [{ count: totalData }];
        const filteredCount = totalFiltered.length > 0 ? totalFiltered[0].count : 0;

        pipeline.push({ $sort: { [orderColumn]: orderDir === 'asc' ? 1 : -1 } });
        pipeline.push({ $skip: start });
        pipeline.push({ $limit: limit });

        pipeline.push({
            $project: {
                _id: 1,
                request_amount: 1,
                request_number: 1,
                request_status: 1,
                payment_receipt: 1,
                insert_date: '$insert_date_formatted',
                user_id: 1,
                'userData.user_name': 1,
                'userData.mobile': 1
            }
        });

        const tb_data = await withdraw_fund_request_module.aggregate(pipeline);

        const BASE_URL = process.env.BASE_URL || 'http://yourdomain.com/';
        const ADMIN_PATH = 'admin';

        // Format data as expected
        let data = [];
        let i = start + 1;
        for (const rs of tb_data) {
            const receipt_img = rs.payment_receipt
                ? `<li><a class="item" href="${BASE_URL}uploads/file/${rs.payment_receipt}" title=""><img class="icons" src="${BASE_URL}uploads/file/${rs.payment_receipt}"></a></li>`
                : 'N/A';

            let display_status = '';
            if (rs.request_status === 0) display_status = '<badge class="badge badge-pill badge-soft-info font-size-12">Pending</badge>';
            else if (rs.request_status === 1) display_status = '<badge class="badge badge-pill badge-soft-danger font-size-12">Rejected</badge>';
            else display_status = '<badge class="badge badge-pill badge-soft-success font-size-12">Accepted</badge>';

            let action = '';
            if (rs.request_status === 1 || rs.request_status === 2) {
                action = `
          <button class="btn btn-primary btn-sm w-xs mr-1" data-withdraw_request_id="${rs.withdraw_request_id}" disabled>Approve</button>
          <button class="btn btn-danger btn-sm w-xs" data-withdraw_request_id="${rs.withdraw_request_id}" disabled>Reject</button>
        `;
            } else {
                action = `
          <button class="btn btn-primary btn-sm w-xs mr-1" id="accept" data-withdraw_request_id="${rs.withdraw_request_id}" data-user_name="${rs.user.user_name}" data-mobile="${rs.user.mobile}" data-request_amount="${rs.request_amount}" data-request_number="${rs.request_number}">Approve</button>
          <button class="btn btn-danger btn-sm w-xs" id="reject" data-withdraw_request_id="${rs.withdraw_request_id}">Reject</button>
        `;
            }

            data.push({
                '#': i++,
                user_name: `${rs.user.user_name} <a href="${BASE_URL}${ADMIN_PATH}/view-user/${rs.user_id}"><i class="bx bx-link-external"></i></a>`,
                mobile: rs.user.mobile,
                request_amount: rs.request_amount,
                request_number: rs.request_number,
                receipt_img,
                insert_date: rs.insert_date,
                request_status: rs.request_status,
                withdraw_request_id: rs.withdraw_request_id,
                display_status,
                view: `<a role="button" data-href="${BASE_URL}${ADMIN_PATH}/view-withdraw-request/${rs.withdraw_request_id}" class="mr-3 text-primary openViewWithdrawRequest" data-toggle="tooltip" data-placement="top" title="View Details"><i class="mdi mdi-eye font-size-18"></i></a>`,
                action
            });
        }

        res.json({
            draw: parseInt(req.body.draw) || 1,
            recordsTotal: totalData,
            recordsFiltered: searchValue ? filteredCount : totalData,
            data
        });

    } catch (error) {
        console.error('Error in withdrawRequestListGridData:', error);
        res.status(500).json({ error: 'Internal Server Error' });
    }
}

const ideaListGridData = async (req, res) => {
    try {
        const columns = ['_id', 'user_name', 'ideas', 'insert_date'];

        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const orderColumnIndex = parseInt(req?.body?.order?.[0]?.column) || 0;
        const orderColumn = columns[orderColumnIndex] || '_id';
        const orderDir = req?.body?.order?.[0]?.dir === 'desc' ? -1 : 1;
        const searchValue = req?.body?.search?.value?.trim() || '';

        let filter = {};

        if (searchValue) {
            filter.$or = [
                { user_name: { $regex: '^' + searchValue, $options: 'i' } },
                { ideas: { $regex: '^' + searchValue, $options: 'i' } },
            ];
        }

        const totalRecords = await ideas_module.countDocuments({});
        const totalFilteredRecords = await ideas_module.countDocuments(filter);

        const results = await ideas_module
            .find(filter)
            .sort({ [orderColumn]: orderDir })
            .skip(start)
            .limit(limit);

        const data = results.map(idea => ({
            user_name: idea.user_name,
            idea: idea.ideas,
            insert_date: idea.insert_date
                ? new Date(idea.insert_date).toLocaleString('en-GB', {
                    day: '2-digit',
                    month: 'short',
                    year: 'numeric',
                    hour: '2-digit',
                    minute: '2-digit'
                })
                : '-'
        }));

        return res.json({
            success: true,
            draw: parseInt(req.body.draw) || 1,
            recordsTotal: totalRecords,
            recordsFiltered: totalFilteredRecords,
            data
        });
    } catch (err) {
        console.error('Error loading idea list:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal server error'
        });
    }
};

const addAdminBankDetail = async (req, res) => {
    try {
        let {
            accountDB_id = '',
            ac_name = '',
            ac_number = '',
            ifsc_code = '',
            upi_payment_id = ''
        } = req?.body || {};

        accountDB_id = toStr(accountDB_id);
        ac_name = toStr(ac_name);
        ac_number = toStr(ac_number);
        ifsc_code = toStr(ifsc_code);
        upi_payment_id = toStr(upi_payment_id);

        if (!accountDB_id || !ac_name || !ac_number || !ifsc_code || !upi_payment_id) {
            return res.status(400).json({
                success: false,
                msg: 'All fields are Required'
            });
        }

        if (accountDB_id && !mongoose.isValidObjectId(accountDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid account ID.'
            });
        }

        const adminData = {
            ac_holder_name: ac_name.trim().replace(/\b\w/g, c => c.toUpperCase()),
            account_number: ac_number.trim(),
            ifsc_code: ifsc_code.trim().toUpperCase(),
            upi_payment_id: upi_payment_id.trim(),
        };

        let response = {};

        if (!accountDB_id) {
            await admin_bank_detail_module.create(adminData);
            response.success = true;
            response.msg = 'Bank details successfully added.';
        } else {
            await admin_bank_detail_module.findByIdAndUpdate(accountDB_id, adminData);
            response.success = true;
            response.msg = 'Bank details successfully updated.';
        }

        res.json(response);
    } catch (error) {
        console.error('Error in addAdminBankDetail:', error);
        res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
};

const addAdminUpiUpdateOtpCheck = async (req, res) => {
    try {
        let {
            adminDB_id,
            upi_id,
            google_upi_payment_id,
            phonepay_upi_payment_id,
            otp_code,
        } = req?.body || {};

        adminDB_id = toStr(adminDB_id);
        upi_id = toStr(upi_id);
        google_upi_payment_id = toStr(google_upi_payment_id);
        phonepay_upi_payment_id = toStr(phonepay_upi_payment_id);
        otp_code = Number(toStr(otp_code));

        if (
            !adminDB_id ||
            !upi_id ||
            !google_upi_payment_id ||
            !phonepay_upi_payment_id ||
            !otp_code
        ) {
            return res.status(400).json({
                success: false,
                msg: 'All fields (admin ID, UPI IDs, and OTP) are required.',
            });
        }

        if (!mongoose.isValidObjectId(adminDB_id)) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid admin ID format.',
            });
        }

        const otp_document = await otp_module.findOne({
            userDB_id: adminDB_id,
            userDB_model: "Admin",
        });

        if (!otp_document) {
            return res.status(404).json({
                success: false,
                msg: 'OTP not found. Please request a new one.',
            });
        }

        if (otp_code !== otp_document?.otp_code) {
            return res.status(400).json({
                success: false,
                msg: 'Incorrect OTP. Please try again.',
            });
        }

        const existingRecord = await admin_bank_detail_module.findOne({ userDB_id: adminDB_id });

        const adminData = {
            upi_payment_id: upi_id.trim(),
            google_upi_payment_id: google_upi_payment_id.trim(),
            phonepay_upi_payment_id: phonepay_upi_payment_id.trim(),
        };

        if (existingRecord) {
            await admin_bank_detail_module.updateOne({ userDB_id: adminDB_id }, adminData);
        } else {
            await new admin_bank_detail_module({ userDB_id: adminDB_id, ...adminData }).save();
        }

        await new admin_upi_update_record_module({
            admin_id: adminDB_id,
            upi_id,
            update_date: new Date(),
        }).save();

        await otp_module.deleteMany({
            $or: [
                { userDB_id: adminDB_id },
                {
                    $and: [
                        { otp: otp_document?.otp_code },
                        { userDB_id }
                    ]
                }
            ]
        });

        return res.json({
            success: true,
            msg: 'UPI ID successfully updated.',
        });

    } catch (error) {
        console.error('Error in addAdminUpiUpdateOtpCheck:', error);
        return res.status(500).json({ success: false, msg: 'Server error' });
    }
};

const lotteryNameListGridData = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }
        const columns = [
            '_id', 'lottery_name', 'lottery_name_hindi', 'no_of_tickets',
            'start_from', 'open_date', 'close_date', 'price',
            'first_prize', 'second_prize', 'third_prize', 'status',
            'market_status', '_id'
        ];

        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const orderColumnIndex = req?.body?.order?.[0]?.column || 0;
        const orderField = columns[orderColumnIndex] || '_id';
        const orderDir = req?.body?.order?.[0]?.dir === 'asc' ? 1 : -1;
        const search = req?.body?.search?.value?.trim() || '';

        let filter = {};
        if (search !== '') {
            filter = {
                lottery_name: { $regex: `^${search}`, $options: 'i' }
            };
        }

        const totalData = await lottery_module.countDocuments();
        const totalFiltered = await lottery_module.countDocuments(filter);

        const tb_data = await lottery_module.find(filter)
            .sort({ [orderField]: orderDir })
            .skip(start)
            .limit(limit)
            .lean();

        const data = tb_data.map((rs) => {
            const imageUrl = `${baseUrl}/file/uploads/images/${rs?.lottery_image?.toString()}`;
            return {
                lottery_name: rs.lottery_name?.toUpperCase() || '',
                lottery_name_hindi: rs.lottery_name_hindi || '',
                no_of_tickets: rs.no_of_tickets,
                start_from: rs.start_from,
                open_date: rs.open_date,
                close_date: rs.close_date,
                price: rs.price,
                first_prize: rs.first_prize?.toFixed(2),
                second_prize: rs.second_prize?.toFixed(2),
                third_prize: rs.third_prize?.toFixed(2),
                image: `<a href="${imageUrl}" target="_blank"><img src="${imageUrl}" width="100px" height="100px"/></a>`,
                status: rs.status,
                market_status: rs.market_status,
                lotteryDB_id: rs._id,
                display_status: rs.status === 1
                    ? `<a role="button" class="activeDeactive" id="success-${rs._id}-tb_lottery-lotteryDB_id-status"><span class="badge badge-pill badge-soft-success font-size-12">Yes</span></a>`
                    : `<a role="button" class="activeDeactive" id="danger-${rs._id}-tb_lottery-lotteryDB_id-status"><span class="badge badge-pill badge-soft-danger font-size-12">No</span></a>`
            };
        });

        return res.json({
            success: true,
            draw: parseInt(req.body.draw) || 1,
            recordsTotal: totalData,
            recordsFiltered: totalFiltered,
            data: data
        });

    } catch (err) {
        console.error("Error in lotteryListGridData:", err);
        return res.status(500).json({ success: false, error: 'Something went wrong.' });
    }
}

const addLottery = async (req, res) => {
    try {
        const {
            lotteryDB_id = "",
            lottery_name = "",
            lottery_name_hindi = "",
            no_of_tickets = "",
            start_from = "",
            price = "",
            first_rank = "",
            second_rank = "",
            third_rank = "",
            open_date = "",
            close_date = ""
        } = req?.body || {};

        lotteryDB_id = toStr(lotteryDB_id);
        lottery_name = toStr(lottery_name);
        lottery_name_hindi = toStr(lottery_name_hindi);
        no_of_tickets = Number(toStr(no_of_tickets));
        start_from = Number(toStr(start_from));
        price = Number(toStr(price));
        first_rank = Number(toStr(first_rank));
        second_rank = Number(toStr(second_rank));
        third_rank = Number(toStr(third_rank));
        open_date = toStr(open_date);
        close_date = toStr(close_date);

        if (!lotteryDB_id || !lottery_name || !lottery_name_hindi || !no_of_tickets || !start_from || !price || !first_rank || !second_rank || !third_rank || !open_date || !close_date) {
            return res.status(400).json({ success: false, msg: 'all Fields are required' });
        }

        if (!mongoose.isValidObjectId(lotteryDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid lotteryDB_id' });
        }

        const formatDate = (dateStr) => {
            const date = new Date(dateStr);
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
            const day = String(date.getDate()).padStart(2, '0');
            return `${year}-${month}-${day}`;
        };

        const openDateFormatted = formatDate(open_date);
        const closeDateFormatted = formatDate(close_date);

        if (!req.file || !req.file.buffer || !req.file.mimetype) {
            return res.status(400).json({ success: false, msg: 'Valid file is required' });
        }

        const image = new file_module({
            fileBuffer: req.file.buffer,
            content_type: req.file.mimetype
        });
        const savedImage = await image.save();

        const lotteryData = {
            lottery_name: lottery_name.toUpperCase(),
            lottery_name_hindi,
            no_of_tickets: parseInt(no_of_tickets),
            start_from: parseInt(start_from),
            price: parseFloat(price),
            first_prize: first_rank,
            second_prize: second_rank,
            third_prize: third_rank,
            open_date: openDateFormatted,
            open_date_sort: openDateFormatted,
            close_date: closeDateFormatted,
            lottery_image: savedImage._id
        };

        let lotteryDocument = await lottery_module.findById(lotteryDB_id)

        if (!lotteryDocument) {
            const newLottery = await lottery_module.create(lotteryData);
            const newLotteryId = newLottery._id;

            let ticketInsertArray = [];
            for (let i = parseInt(start_from); i < parseInt(start_from) + parseInt(no_of_tickets); i++) {
                ticketInsertArray.push({
                    lotteryDB_id: newLotteryId,
                    ticket_number: i,
                    status: 'available'
                });
            }
            await lottery_tickets_module.insertMany(ticketInsertArray);

            return res.json({ success: true, msg: 'Lottery added successfully' });
        } else {
            const existingId = lotteryDocument._id;

            await lottery_module.findByIdAndUpdate(existingId, lotteryData);

            for (let i = parseInt(start_from); i < parseInt(start_from) + parseInt(no_of_tickets); i++) {
                const existingTicket = await lottery_tickets_module.findOne({ lotteryDB_id: existingId, ticket_number: i });
                const ticketData = {
                    lotteryDB_id: existingId,
                    ticket_number: i
                };
                if (existingTicket) {
                    await lottery_tickets_module.findByIdAndUpdate(existingTicket._id, ticketData);
                } else {
                    await lottery_tickets_module.create({ ...ticketData, status: 'available' });
                }
            }
            return res.json({ success: true, msg: 'Lottery updated successfully' });
        }
    } catch (err) {
        console.error(err);
        res.status(500).json({ success: false, msg: 'Server error' });
    }
};

const deleteLottery = async (req, res) => {
    try {
        const { lotteryDB_id = "" } = req?.body || {};

        if (!lotteryDB_id) {
            return res.status(400).json({ success: false, msg: "lottery_id is required" });
        }

        if (!mongoose.isValidObjectId(lotteryDB_id)) {
            return res.status(400).json({ success: false, msg: 'Invalid lotteryDB_id' });
        }

        await lottery_module.deleteOne({ lotteryDB_id });

        res.json({
            success: true,
            msg: "delete Successfully done."
        });
    } catch (error) {
        console.error("Delete Lottery Error:", error);
        res.status(500).json({
            success: false,
            msg: "Something went wrong while deleting lottery."
        });
    }
};







// const deleteOpenResultData_Result = async (req, res) => {
//     const { gameDB_id, result_dec_date } = req.body
//     try {
//         const istDate = moment_timeZone.tz(result_dec_date, 'Asia/Kolkata');
//         const startDate = istDate.clone().startOf('day').toDate();
//         const endDate = istDate.clone().endOf('day').toDate();

//         const result = await game_result_history_module.findOne({ gameDB_id, result_date: { $gte: startDate, $lte: endDate }, })

//         if (result == null) {
//             return res.status(400).json({ success: false, message: "Game result is not decleare yet" })
//         } else {
//             const open_result_token = result.open_result_token
//             if (open_result_token != '') {
//                 await bid_history_module.updateMany({ open_result_token: open_result_token }, { $set: { pay_status: 0 } })
//                 await user_notification_module.deleteMany({ userDB_id: result?.userDB_id })
//                 await game_result_history_module.deleteOne({ gameDB_id, result_date: { $gte: startDate, $lte: endDate } })
//             }
//             return res.status(200).json({ success: true, message: "Open result deleted successfully" })
//         }

//     } catch (error) {
//         console.log("error in deleteOpenResultData_Result", error);
//         return res.status(500).json({ success: false, message: error.message })
//     }
// };

// const deleteCloseResultData = async (req, res) => {
//     try {
//         const istDate = moment_timeZone.tz(result_dec_date, 'Asia/Kolkata');
//         const startDate = istDate.clone().startOf('day').toDate();
//         const endDate = istDate.clone().endOf('day').toDate();

//         const result = await game_result_history_module.findOne({ gameDB_id, result_date: { $gte: startDate, $lte: endDate }, })

//         if (result == null) {
//             return res.status(400).json({ success: false, message: "Game result is not decleare yet" })
//         } else {
//             const open_result_token = result.open_result_token
//             if (open_result_token != '') {
//                 await bid_history_module.updateMany({ open_result_token: open_result_token }, { $set: { pay_status: 0 } })
//                 await user_notification_module.deleteMany({ userDB_id: result?.userDB_id })
//                 await game_result_history_module.deleteOne({ gameDB_id, result_date: { $gte: startDate, $lte: endDate } })
//             }
//             return res.status(200).json({ success: true, message: "Open result deleted successfully" })
//         }

//     } catch (error) {
//         console.log("error in deleteOpenResultData_Result", error);
//         return res.status(500).json({ success: false, message: error.message })
//     }
// };





// const deleteOpenCloseResultData_Result = async (req, res) => {
//     const { gameDB_id, result_dec_date, resultId } = req.body;

//     console.log("req.body of open result delete", req.body);

//     try {
//         // Use the result_date_long from the frontend which is in proper ISO format
//         const resultDate = new Date(result_dec_date);
//         console.log("ðŸš€ ~ deleteOpenResultData_Result ~ resultDate:", resultDate)

//         if (isNaN(resultDate.getTime())) {
//             return res.status(400).json({
//                 success: false,
//                 message: "Invalid date format provided"
//             });
//         }
//         // return res.status(200).json("success")

//         // Find the result using the exact result_date_long
//         const result = await game_result_history_module.findOne({
//             _id: resultId,
//             gameDB_id,
//             result_date: resultDate
//         });

//         if (!result) {
//             return res.status(400).json({
//                 success: false,
//                 message: "Game result not found for the specified date"
//             });
//         }

//         // Delete both open and close results
//         const open_result_token = result.open_result_token;
//         console.log("ðŸš€ ~ deleteOpenResultData_Result ~ open_result_token:", open_result_token)
//         const close_result_token = result.close_result_token;
//         console.log("ðŸš€ ~ deleteOpenResultData_Result ~ close_result_token:", close_result_token)

//         if (open_result_token) {
//             await bid_history_module.updateMany(
//                 { open_result_token: open_result_token },
//                 { $set: { pay_status: 0 } }
//             );
//         }

//         if (close_result_token) {
//             await bid_history_module.updateMany(
//                 { close_result_token: close_result_token },
//                 { $set: { pay_status: 0 } }
//             );
//         }

//         // Delete user notifications and the result document
//         // await user_notification_module.deleteMany({ userDB_id: result?.userDB_id });
//         await game_result_history_module.deleteOne({
//             gameDB_id,
//             result_date: resultDate
//         });

//         return res.status(200).json({
//             success: true,
//             message: "Both open and close results deleted successfully"
//         });

//     } catch (error) {
//         console.log("Error in deleteOpenResultData_Result", error);
//         return res.status(500).json({
//             success: false,
//             message: error.message
//         });
//     }
// };

const deleteOpenCloseResultData_Result = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date, resultId } = req.body;

        console.log("req.body of open result delete", req.body);

        // Use the result_date_long from the frontend which is in proper ISO format
        const resultDate = new Date(result_dec_date);
        console.log("ðŸš€ ~ deleteOpenResultData_Result ~ resultDate:", resultDate)

        if (isNaN(resultDate.getTime())) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Invalid date format provided"
            });
        }

        // Find the result using the exact result_date_long
        const result = await game_result_history_module.findOne({
            _id: resultId,
            gameDB_id,
            result_date: resultDate
        }).session(session);

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Game result not found for the specified date"
            });
        }

        // Get both open and close result tokens
        const open_result_token = result.open_result_token;
        const close_result_token = result.close_result_token;
        console.log("ðŸš€ ~ deleteOpenResultData_Result ~ open_result_token:", open_result_token)
        console.log("ðŸš€ ~ deleteOpenResultData_Result ~ close_result_token:", close_result_token)

        // Process OPEN result refunds
        if (open_result_token && result.open_decleare_status === 1) {
            await processResultRefund({
                result_token: open_result_token,
                session_type: 'open',
                gameDB_id,
                resultDate,
                mongooseSession: session
            });
        }

        // Process CLOSE result refunds
        if (close_result_token && result.close_decleare_status === 1) {
            await processResultRefund({
                result_token: close_result_token,
                session_type: 'close',
                gameDB_id,
                resultDate,
                mongooseSession: session
            });
        }

        // Delete user notifications for this result
        await user_notification_module.deleteMany({
            $or: [
                { msg: { $regex: result.open_number, $options: 'i' } },
                { msg: { $regex: result.close_number, $options: 'i' } }
            ]
        }).session(session);

        // Delete the result document
        await game_result_history_module.deleteOne({
            _id: resultId,
            gameDB_id,
            result_date: resultDate
        }).session(session);

        await session.commitTransaction();
        session.endSession();

        return res.status(200).json({
            success: true,
            message: "Both open and close results deleted successfully. Winning amounts deducted from user wallets."
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("Error in deleteOpenResultData_Result", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};

// Helper function to process refunds for a specific session (open/close)  helper funciton of the deleteOpenCloseResultdata result api
const processResultRefund = async ({ result_token, session_type, gameDB_id, resultDate, mongooseSession }) => {
    console.log("ðŸš€ ~ processResultRefund ~ result_token:", result_token)
    try {
        // Find all winning bids for this result token
        const winningBids = await bid_history_module.find({
            [session_type === 'open' ? 'open_result_token' : 'close_result_token']: result_token
        }).session(mongooseSession);
        // const winningBids = await bid_history_module.find({
        //     bid_date: resultDate
        // }).session(mongooseSession);

        console.log("ðŸš€ ~ processResultRefund ~ winningBids:", winningBids)

        console.log(`ðŸ” Found ${winningBids.length} winning bids for ${session_type} result`);

        for (const bid of winningBids) {
            // Find wallet transaction to get the exact winning amount
            const walletTransaction = await wallet_trans_history_module.findOne({
                [session_type === 'open' ? 'open_result_token' : 'close_result_token']: result_token,
                bid_tx_id: bid.bid_tx_id,
                transaction_type: 1, // Credit transaction
                amount_status: 8 // Winning amount
            }).session(mongooseSession);

            if (walletTransaction) {
                const refundAmount = walletTransaction.amount;
                const userDB_id = bid.userDB_id;
                const bid_tx_id = bid.bid_tx_id;

                console.log(`ðŸ’¸ Processing refund of ${refundAmount} for user ${userDB_id}`);

                // Get current wallet balance before deduction
                const userData = await user_module.findById(userDB_id, { wallet_balance: 1 }).session(mongooseSession);
                const before_wallet = userData.wallet_balance;

                // Check if user has sufficient balance
                if (userData.wallet_balance < refundAmount) {
                    console.warn(`âš ï¸ User ${userDB_id} has insufficient balance for refund`);
                    continue;
                }

                // Generate unique transaction token
                const refundTxToken = getUserRandomToken();

                // Create refund transaction record
                // await new wallet_trans_history_module({
                //     userDB_id,
                //     amount: refundAmount,
                //     transaction_type: 2, // Debit transaction
                //     amount_status: 9, // Result cancellation refund
                //     transaction_note: `Result cancellation - ${session_type.charAt(0).toUpperCase() + session_type.slice(1)} session winning amount deducted`,
                //     tx_request_number: refundTxToken,
                //     bid_tx_id,
                //     [session_type === 'open' ? 'open_result_token' : 'close_result_token']: result_token,
                //     before_wallet,
                //     after_wallet: before_wallet - refundAmount
                // }).save({ session: mongooseSession });

                // Deduct amount from user wallet
                await user_module.findByIdAndUpdate(
                    userDB_id,
                    { $inc: { wallet_balance: -refundAmount } },
                    { new: true, session: mongooseSession }
                );

                console.log(`âœ… Successfully deducted ${refundAmount} from user ${userDB_id}`);
            }

            // Update bid pay_status to 0 (not paid) regardless of refund success
            await bid_history_module.updateOne(
                { _id: bid._id },
                { $set: { pay_status: 0 } },
                { session: mongooseSession }
            );
        }

        // Delete any remaining wallet transactions for this result token
        await wallet_trans_history_module.deleteMany({
            [session_type === 'open' ? 'open_result_token' : 'close_result_token']: result_token
        }).session(mongooseSession);

    } catch (error) {
        console.error(`Error processing ${session_type} result refund:`, error);
        throw error;
    }
};


const revertBidCompletely = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date, resultId } = req.body;

        console.log("ðŸš€ ~ revertBidCompletely ~ req.body:", req.body);

        if (!gameDB_id || !resultId) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Game DB ID and Result ID are required"
            });
        }

        // Step 1: Find the game result
        const resultDate = new Date(result_dec_date);
        const gameResult = await game_result_history_module.findOne({
            _id: resultId,
            gameDB_id: gameDB_id,
            result_date: resultDate
        }).session(session);

        if (!gameResult) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "Game result not found"
            });
        }

        const open_result_token = gameResult.open_result_token;
        const close_result_token = gameResult.close_result_token;

        console.log("ðŸ” Found game result with tokens:", { open_result_token, close_result_token });

        // Step 2: Find ALL bids associated with these result tokens (both winning and losing)
        const allBids = await bid_history_module.find({
            $or: [
                { open_result_token: open_result_token },
                { close_result_token: close_result_token }
            ],
            gameDB_id: gameDB_id,
            bid_date: resultDate
        }).session(session);

        console.log(`ðŸ” Found ${allBids.length} bids to revert`);

        if (allBids.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "No bids found for this game result"
            });
        }

        let totalRefundedAmount = 0;
        let revertedBidsCount = 0;
        let totalBidAmount = 0;
        let totalWinningAmount = 0;

        // Step 3: Process each bid individually
        for (const bid of allBids) {
            try {
                const refundResult = await processSingleBidRevert({
                    bid,
                    session
                });

                totalRefundedAmount += refundResult.refundAmount;
                totalBidAmount += refundResult.bidAmount;
                totalWinningAmount += refundResult.winningAmount;
                revertedBidsCount++;

                console.log(`âœ… Successfully reverted bid: ${bid.bid_tx_id}, refunded: ${refundResult.refundAmount}`);
            } catch (bidError) {
                console.error(`âŒ Failed to revert bid ${bid.bid_tx_id}:`, bidError);
                // Continue with other bids even if one fails
            }
        }

        // Step 4: Delete the game result document
        await game_result_history_module.deleteOne({
            _id: resultId,
            gameDB_id: gameDB_id,
            result_date: resultDate
        }).session(session);

        console.log(`ðŸ—‘ï¸ Deleted game result: ${resultId}`);

        // Step 5: Delete user notifications for this result
        await user_notification_module.deleteMany({
            $or: [
                { msg: { $regex: gameResult.open_number, $options: 'i' } },
                { msg: { $regex: gameResult.close_number, $options: 'i' } }
            ]
        }).session(session);

        console.log(`ðŸ—‘ï¸ Deleted related notifications`);

        await session.commitTransaction();
        session.endSession();

        return res.status(200).json({
            success: true,
            message: `Successfully reverted ${revertedBidsCount} bids and deleted game result. Total refunded: ${totalRefundedAmount} points.`,
            data: {
                revertedBidsCount,
                totalRefundedAmount,
                totalBidAmount,
                totalWinningAmount,
                deletedResult: resultId
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("âŒ Error in revertBidCompletely", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};

// comment for only change this part
// Helper function to process single bid revert
// const processSingleBidRevert = async ({ bid, session }) => {
//     const userDB_id = bid.userDB_id;
//     const bid_tx_id = bid.bid_tx_id;

//     console.log(`ðŸ”„ Processing bid revert for: ${bid_tx_id}, user: ${userDB_id}`);

//     // Step 1: Get user current wallet balance
//     const user = await user_module.findById(userDB_id).session(session);
//     if (!user) {
//         throw new Error(`User ${userDB_id} not found`);
//     }

//     // Step 2: Find ALL wallet transactions for this bid
//     const walletTransactions = await wallet_trans_history_module.find({
//         bid_tx_id: bid_tx_id
//     }).session(session);

//     console.log(`ðŸ” Found ${walletTransactions.length} wallet transactions for bid ${bid_tx_id}`);

//     let totalBidAmount = 0;  // Total amount user spent on this bid
//     let totalWinningAmount = 0; // Total winning amount user received
//     let netRefundAmount = 0; // Final amount to refund

//     // Step 3: Calculate amounts from wallet transactions
//     for (const transaction of walletTransactions) {
//         if (transaction.transaction_type === 2 && transaction.amount_status === 5) { 
//             // Debit - Bid placed amount
//             totalBidAmount += transaction.amount;
//         } else if (transaction.transaction_type === 1 && transaction.amount_status === 8) { 
//             // Credit - Winning amount
//             totalWinningAmount += transaction.amount;
//         }
//     }

//     // Calculate net refund: Bid amount - Winning amount already received
//     netRefundAmount = totalBidAmount - totalWinningAmount;

//     console.log(`ðŸ’° Amounts for bid ${bid_tx_id}:`, {
//         totalBidAmount,
//         totalWinningAmount,
//         netRefundAmount
//     });

//     // Step 4: Process wallet adjustments
//     if (netRefundAmount > 0) {
//         // User needs refund (they paid more than they won)
//         const before_wallet = user.wallet_balance;
//         const refundTxToken = getUserRandomToken();

//         // Create refund transaction record
//         await new wallet_trans_history_module({
//             userDB_id: userDB_id,
//             amount: netRefundAmount,
//             transaction_type: 1, // Credit transaction (refund)
//             amount_status: 10, // Bid revert refund
//             transaction_note: `Bid reverted - Refund for cancelled bid (TX: ${bid_tx_id})`,
//             tx_request_number: refundTxToken,
//             bid_tx_id: bid_tx_id,
//             before_wallet: before_wallet,
//             after_wallet: before_wallet + netRefundAmount,
//             is_reverted: true
//         }).save({ session: session });

//         // Add refund amount to user wallet
//         await user_module.findByIdAndUpdate(
//             userDB_id,
//             { $inc: { wallet_balance: netRefundAmount } },
//             { new: true, session: session }
//         );

//         console.log(`ðŸ’¸ Refunded ${netRefundAmount} to user ${userDB_id}`);
//     } else if (netRefundAmount < 0) {
//         // User owes money (they won more than they paid) - This shouldn't happen normally
//         const amountToDeduct = Math.abs(netRefundAmount);
//         const before_wallet = user.wallet_balance;

//         // Create deduction transaction record
//         await new wallet_trans_history_module({
//             userDB_id: userDB_id,
//             amount: amountToDeduct,
//             transaction_type: 2, // Debit transaction
//             amount_status: 9, // Result cancellation deduction
//             transaction_note: `Bid reverted - Excess winning amount deducted (TX: ${bid_tx_id})`,
//             tx_request_number: getUserRandomToken(),
//             bid_tx_id: bid_tx_id,
//             before_wallet: before_wallet,
//             after_wallet: before_wallet - amountToDeduct,
//             is_reverted: true
//         }).save({ session: session });

//         // Deduct amount from user wallet
//         await user_module.findByIdAndUpdate(
//             userDB_id,
//             { $inc: { wallet_balance: -amountToDeduct } },
//             { new: true, session: session }
//         );

//         console.log(`ðŸ’¸ Deducted ${amountToDeduct} from user ${userDB_id}`);
//     }

//     // Step 5: Delete ALL wallet transactions for this bid (both bid placed and winning transactions)
//     const deleteWalletResult = await wallet_trans_history_module.deleteMany({
//         bid_tx_id: bid_tx_id
//     }).session(session);

//     console.log(`ðŸ—‘ï¸ Deleted ${deleteWalletResult.deletedCount} wallet transactions for bid ${bid_tx_id}`);

//     // Step 6: Delete the bid itself
//     await bid_history_module.deleteOne({
//         bid_tx_id: bid_tx_id,
//         userDB_id: userDB_id
//     }).session(session);

//     console.log(`ðŸ—‘ï¸ Deleted bid: ${bid_tx_id}`);

//     return {
//         refundAmount: netRefundAmount > 0 ? netRefundAmount : 0,
//         bidAmount: totalBidAmount,
//         winningAmount: totalWinningAmount
//     };
// };

// const revertBidCompletely = async (req, res) => {
//     const session = await mongoose.startSession();
//     session.startTransaction();

//     try {
//         const { gameDB_id, result_dec_date, resultId } = req.body;

//         console.log("ðŸš€ ~ revertBidCompletely ~ req.body:", req.body);

//         if (!gameDB_id || !resultId) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({
//                 success: false,
//                 message: "Game DB ID and Result ID are required"
//             });
//         }

//         // Step 1: Find the game result
//         const resultDate = new Date(result_dec_date);
//         const gameResult = await game_result_history_module.findOne({
//             _id: resultId,
//             gameDB_id: gameDB_id,
//             result_date: resultDate
//         }).session(session);

//         if (!gameResult) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({
//                 success: false,
//                 message: "Game result not found"
//             });
//         }

//         const open_result_token = gameResult.open_result_token;
//         const close_result_token = gameResult.close_result_token;

//         console.log("ðŸ” Found game result with tokens:", { open_result_token, close_result_token });

//         // Step 2: Find ALL bids associated with these result tokens (both winning and losing)
//         const allBids = await bid_history_module.find({
//             $or: [
//                 { open_result_token: open_result_token },
//                 { close_result_token: close_result_token }
//             ],
//             gameDB_id: gameDB_id,
//             bid_date: resultDate
//         }).session(session);

//         console.log(`ðŸ” Found ${allBids.length} bids to revert`);

//         if (allBids.length === 0) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({
//                 success: false,
//                 message: "No bids found for this game result"
//             });
//         }

//         let totalRefundedAmount = 0;
//         let revertedBidsCount = 0;

//         // Step 3: Process each bid individually
//         for (const bid of allBids) {
//             try {
//                 const refundAmount = await processSingleBidRevert({
//                     bid,
//                     session,
//                     open_result_token,
//                     close_result_token
//                 });

//                 totalRefundedAmount += refundAmount;
//                 revertedBidsCount++;

//                 console.log(`âœ… Successfully reverted bid: ${bid.bid_tx_id}, refunded: ${refundAmount}`);
//             } catch (bidError) {
//                 console.error(`âŒ Failed to revert bid ${bid.bid_tx_id}:`, bidError);
//                 // Continue with other bids even if one fails
//             }
//         }

//         // Step 4: Delete the game result document
//         await game_result_history_module.deleteOne({
//             _id: resultId,
//             gameDB_id: gameDB_id,
//             result_date: resultDate
//         }).session(session);

//         console.log(`ðŸ—‘ï¸ Deleted game result: ${resultId}`);

//         // Step 5: Delete user notifications for this result
//         await user_notification_module.deleteMany({
//             $or: [
//                 { msg: { $regex: gameResult.open_number, $options: 'i' } },
//                 { msg: { $regex: gameResult.close_number, $options: 'i' } }
//             ]
//         }).session(session);

//         console.log(`ðŸ—‘ï¸ Deleted related notifications`);

//         await session.commitTransaction();
//         session.endSession();

//         return res.status(200).json({
//             success: true,
//             message: `Successfully reverted ${revertedBidsCount} bids and deleted game result. Total refunded: ${totalRefundedAmount} points.`,
//             data: {
//                 revertedBidsCount,
//                 totalRefundedAmount,
//                 deletedResult: resultId
//             }
//         });

//     } catch (error) {
//         await session.abortTransaction();
//         session.endSession();
//         console.log("âŒ Error in revertBidCompletely", error);
//         return res.status(500).json({
//             success: false,
//             message: error.message
//         });
//     }
// };

// // Helper function of revertBidCompletely for process single bid revert
// const processSingleBidRevert = async ({ bid, session, open_result_token, close_result_token }) => {
//     let totalRefundAmount = 0;
//     const userDB_id = bid.userDB_id;
//     const bid_tx_id = bid.bid_tx_id;

//     console.log(`ðŸ”„ Processing bid revert for: ${bid_tx_id}, user: ${userDB_id}`);

//     // Step 1: Get user current wallet balance
//     const user = await user_module.findById(userDB_id).session(session);
//     if (!user) {
//         throw new Error(`User ${userDB_id} not found`);
//     }

//     // Step 2: Find ALL wallet transactions for this bid
//     const walletTransactions = await wallet_trans_history_module.find({
//         bid_tx_id: bid_tx_id
//     }).session(session);

//     console.log(`ðŸ” Found ${walletTransactions.length} wallet transactions for bid ${bid_tx_id}`);

//     // Step 3: Calculate net refund amount
//     for (const transaction of walletTransactions) {
//         if (transaction.transaction_type === 2) { // Debit (bid placed)
//             totalRefundAmount += transaction.amount; // Refund bid amount
//         } else if (transaction.transaction_type === 1) { // Credit (winning)
//             totalRefundAmount -= transaction.amount; // Deduct winning amount
//         }
//     }

//     // Ensure we don't go negative
//     totalRefundAmount = Math.max(0, totalRefundAmount);

//     console.log(`ðŸ’° Net refund amount for bid ${bid_tx_id}: ${totalRefundAmount}`);

//     // Step 4: Create refund transaction if needed
//     if (totalRefundAmount > 0) {
//         const before_wallet = user.wallet_balance;
//         const refundTxToken = getUserRandomToken();

//         // Create refund transaction record
//         await new wallet_trans_history_module({
//             userDB_id: userDB_id,
//             amount: totalRefundAmount,
//             transaction_type: 1, // Credit transaction (refund)
//             amount_status: 10, // Bid revert refund
//             transaction_note: `Bid reverted - Refund for cancelled bid (TX: ${bid_tx_id})`,
//             tx_request_number: refundTxToken,
//             bid_tx_id: bid_tx_id,
//             before_wallet: before_wallet,
//             after_wallet: before_wallet + totalRefundAmount,
//             is_reverted: true
//         }).save({ session: session });

//         // Add refund amount to user wallet
//         await user_module.findByIdAndUpdate(
//             userDB_id,
//             { $inc: { wallet_balance: totalRefundAmount } },
//             { new: true, session: session }
//         );

//         console.log(`ðŸ’¸ Refunded ${totalRefundAmount} to user ${userDB_id}`);
//     }

//     // Step 5: Delete ALL wallet transactions for this bid
//     const deleteWalletResult = await wallet_trans_history_module.deleteMany({
//         bid_tx_id: bid_tx_id
//     }).session(session);

//     console.log(`ðŸ—‘ï¸ Deleted ${deleteWalletResult.deletedCount} wallet transactions for bid ${bid_tx_id}`);

//     // Step 6: Delete the bid itself
//     await bid_history_module.deleteOne({
//         bid_tx_id: bid_tx_id,
//         userDB_id: userDB_id
//     }).session(session);

//     console.log(`ðŸ—‘ï¸ Deleted bid: ${bid_tx_id}`);

//     return totalRefundAmount;
// };


// const revertBidCompletely = async (req, res) => {
//     const session = await mongoose.startSession();
//     session.startTransaction();

//     try {
//         const {
//             bid_tx_id,
//             userDB_id,
//             gameDB_id,
//             bid_date,
//             points,
//             winning_points,
//             session: bid_session,
//             open_result_token,
//             close_result_token
//         } = req.body;

//         console.log("ðŸš€ ~ revertBidCompletely ~ req.body:", req.body);

//         if (!bid_tx_id || !userDB_id) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({
//                 success: false,
//                 message: "Bid transaction ID and User ID are required"
//             });
//         }

//         // Step 1: Find the bid to verify it exists
//         const bid = await bid_history_module.findOne({
//             bid_tx_id: bid_tx_id,
//             userDB_id: userDB_id
//         }).session(session);

//         if (!bid) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({
//                 success: false,
//                 message: "Bid not found"
//             });
//         }

//         console.log(`ðŸ” Found bid: ${bid_tx_id} with points: ${points}, winning: ${winning_points}`);

//         // Step 2: Handle wallet balance adjustments
//         const user = await user_module.findById(userDB_id).session(session);
//         if (!user) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({
//                 success: false,
//                 message: "User not found"
//             });
//         }

//         let totalRefundAmount = 0;
//         const refundOperations = [];

//         // Step 3: Process wallet transactions and calculate refunds
//         const walletTransactions = await wallet_trans_history_module.find({
//             bid_tx_id: bid_tx_id
//         }).session(session);

//         console.log(`ðŸ” Found ${walletTransactions.length} wallet transactions for this bid`);

//         // Calculate total amount to refund
//         for (const transaction of walletTransactions) {
//             if (transaction.transaction_type === 2) { // Debit (bid placed)
//                 totalRefundAmount += transaction.amount; // Refund the bid amount
//             } else if (transaction.transaction_type === 1) { // Credit (winning)
//                 totalRefundAmount -= transaction.amount; // Deduct winning amount if any
//             }
//         }

//         // Ensure we don't go negative in refund
//         totalRefundAmount = Math.max(0, totalRefundAmount);

//         console.log(`ðŸ’° Total refund amount: ${totalRefundAmount}`);

//         // Step 4: Create refund transaction if needed
//         if (totalRefundAmount > 0) {
//             const before_wallet = user.wallet_balance;
//             const refundTxToken = getUserRandomToken();

//             // Create refund transaction record
//             await new wallet_trans_history_module({
//                 userDB_id: userDB_id,
//                 amount: totalRefundAmount,
//                 transaction_type: 1, // Credit transaction (refund)
//                 amount_status: 10, // Bid revert refund
//                 transaction_note: `Bid reverted - Refund for cancelled bid (TX: ${bid_tx_id})`,
//                 tx_request_number: refundTxToken,
//                 bid_tx_id: bid_tx_id,
//                 before_wallet: before_wallet,
//                 after_wallet: before_wallet + totalRefundAmount,
//                 is_reverted: true
//             }).save({ session: session });

//             // Add refund amount to user wallet
//             await user_module.findByIdAndUpdate(
//                 userDB_id,
//                 { $inc: { wallet_balance: totalRefundAmount } },
//                 { new: true, session: session }
//             );

//             console.log(`âœ… Refunded ${totalRefundAmount} to user ${userDB_id}`);
//         }

//         // Step 5: Delete all wallet transactions for this bid
//         const deleteWalletResult = await wallet_trans_history_module.deleteMany({
//             bid_tx_id: bid_tx_id
//         }).session(session);

//         console.log(`ðŸ—‘ï¸ Deleted ${deleteWalletResult.deletedCount} wallet transactions`);

//         // Step 6: Delete the bid itself
//         await bid_history_module.deleteOne({
//             bid_tx_id: bid_tx_id,
//             userDB_id: userDB_id
//         }).session(session);

//         console.log(`ðŸ—‘ï¸ Deleted bid: ${bid_tx_id}`);

//         // Step 7: Clean up any result associations if this was a winning bid
//         if (open_result_token || close_result_token) {
//             // Update game result history to remove this bid's association
//             // This ensures the result history doesn't reference a deleted bid
//             await game_result_history_module.updateMany(
//                 {
//                     $or: [
//                         { open_result_token: open_result_token },
//                         { close_result_token: close_result_token }
//                     ].filter(condition => condition !== undefined)
//                 },
//                 {
//                     $pull: {
//                         winning_bids: bid_tx_id
//                     }
//                 },
//                 { session: session }
//             );

//             console.log(`ðŸ”„ Cleaned up result associations for bid`);
//         }

//         // Step 8: Delete any user notifications related to this bid
//         await user_notification_module.deleteMany({
//             $or: [
//                 { msg: { $regex: bid_tx_id, $options: 'i' } },
//                 { 'additional_data.bid_tx_id': bid_tx_id }
//             ]
//         }).session(session);

//         console.log(`ðŸ—‘ï¸ Deleted related notifications`);

//         await session.commitTransaction();
//         session.endSession();

//         return res.status(200).json({
//             success: true,
//             message: `Bid completely reverted. Refunded ${totalRefundAmount} points to user wallet. All associated data has been deleted.`,
//             data: {
//                 refundAmount: totalRefundAmount,
//                 deletedBid: bid_tx_id,
//                 deletedWalletTransactions: deleteWalletResult.deletedCount
//             }
//         });

//     } catch (error) {
//         await session.abortTransaction();
//         session.endSession();
//         console.log("âŒ Error in revertBidCompletely", error);
//         return res.status(500).json({
//             success: false,
//             message: error.message
//         });
//     }
// };





// const deleteCloseResultData = async (req, res) => {
//     const { gameDB_id, result_dec_date } = req.body;

//     try {
//         // Use the same logic for close result deletion
//         const resultDate = new Date(result_dec_date);

//         if (isNaN(resultDate.getTime())) {
//             return res.status(400).json({
//                 success: false,
//                 message: "Invalid date format provided"
//             });
//         }

//         const result = await game_result_history_module.findOne({
//             gameDB_id,
//             result_date: resultDate
//         });

//         if (!result) {
//             return res.status(400).json({
//                 success: false,
//                 message: "Game result not found for the specified date"
//             });
//         }

//         const close_result_token = result.close_result_token;

//         if (close_result_token) {
//             await bid_history_module.updateMany(
//                 { close_result_token: close_result_token },
//                 { $set: { pay_status: 0 } }
//             );
//         }

//         await user_notification_module.deleteMany({ userDB_id: result?.userDB_id });
//         await game_result_history_module.deleteOne({
//             gameDB_id,
//             result_date: resultDate
//         });

//         return res.status(200).json({
//             success: true,
//             message: "Close result deleted successfully"
//         });

//     } catch (error) {
//         console.log("Error in deleteCloseResultData", error);
//         return res.status(500).json({
//             success: false,
//             message: error.message
//         });
//     }
// };

// Helper function to process single bid revert - SIMPLIFIED VERSION
const processSingleBidRevert = async ({ bid, session }) => {
    const userDB_id = bid.userDB_id;
    const bid_tx_id = bid.bid_tx_id;

    console.log(`ðŸ”„ Processing bid revert for: ${bid_tx_id}, user: ${userDB_id}`);

    // Step 1: Get user current wallet balance
    const user = await user_module.findById(userDB_id).session(session);
    if (!user) {
        throw new Error(`User ${userDB_id} not found`);
    }

    // Step 2: Calculate the net amount to adjust
    // We need to refund the bid points and deduct any winnings
    const bidPoints = bid.points; // This is the original bid amount
    const winningPoints = bid.winning_points; // This is the potential winning amount
    const pay_status = bid.pay_status;

    console.log(`ðŸ’° Bid details: points=${bidPoints}, winning_points=${winningPoints}, pay_status=${pay_status}`);

    let netAdjustment = 0;
    let transactionNote = '';

    if (pay_status === 1) {
        // Winning bid: refund bid amount and deduct winnings
        netAdjustment = bidPoints - winningPoints;
        transactionNote = `Bid reverted - Refund bid amount and deduct winnings (TX: ${bid_tx_id})`;
    } else {
        // Losing bid or pending: just refund the bid amount
        netAdjustment = bidPoints;
        transactionNote = `Bid reverted - Refund for cancelled bid (TX: ${bid_tx_id})`;
    }

    console.log(`ðŸ’° Net wallet adjustment: ${netAdjustment}`);

    // Step 3: Process wallet adjustment
    if (netAdjustment !== 0) {
        const before_wallet = user.wallet_balance;
        const adjustmentTxToken = getUserRandomToken();

        if (netAdjustment > 0) {
            // Credit to user wallet
            await new wallet_trans_history_module({
                userDB_id: userDB_id,
                amount: Math.abs(netAdjustment),
                transaction_type: 1, // Credit transaction
                amount_status: 10, // Bid revert refund
                transaction_note: transactionNote,
                tx_request_number: adjustmentTxToken,
                bid_tx_id: bid_tx_id,
                before_wallet: before_wallet,
                after_wallet: before_wallet + Math.abs(netAdjustment),
                is_reverted: true
            }).save({ session: session });

            await user_module.findByIdAndUpdate(
                userDB_id,
                { $inc: { wallet_balance: Math.abs(netAdjustment) } },
                { new: true, session: session }
            );
        } else {
            // Debit from user wallet
            await new wallet_trans_history_module({
                userDB_id: userDB_id,
                amount: Math.abs(netAdjustment),
                transaction_type: 2, // Debit transaction
                amount_status: 9, // Winning amount deduction
                transaction_note: transactionNote,
                tx_request_number: adjustmentTxToken,
                bid_tx_id: bid_tx_id,
                before_wallet: before_wallet,
                after_wallet: before_wallet - Math.abs(netAdjustment),
                is_reverted: true
            }).save({ session: session });

            await user_module.findByIdAndUpdate(
                userDB_id,
                { $inc: { wallet_balance: -Math.abs(netAdjustment) } },
                { new: true, session: session }
            );
        }

        console.log(`ðŸ’¸ Adjusted wallet by ${netAdjustment} for user ${userDB_id}`);
    }

    // Step 4: Delete ALL wallet transactions for this bid 
    const deleteWalletResult = await wallet_trans_history_module.deleteMany({
        $or: [
            { bid_tx_id: bid_tx_id },
            { tx_request_number: bid_tx_id }
        ]
    }).session(session);

    console.log(`ðŸ—‘ï¸ Deleted ${deleteWalletResult.deletedCount} wallet transactions for bid ${bid_tx_id}`);

    // Step 5: Delete the bid itself
    await bid_history_module.deleteOne({
        bid_tx_id: bid_tx_id,
        userDB_id: userDB_id
    }).session(session);

    console.log(`ðŸ—‘ï¸ Deleted bid: ${bid_tx_id}`);

    return {
        refundAmount: netAdjustment > 0 ? netAdjustment : 0,
        deductionAmount: netAdjustment < 0 ? Math.abs(netAdjustment) : 0,
        netAdjustment: netAdjustment,
        bidAmount: bidPoints,
        winningAmount: winningPoints
    };
};




const editOpenResultData = async (req, res) => {
    const { game_id, open_number, open_result, result_dec_date } = req.body
    try {
        const data = await game_result_history_module.findOne({ gameDB_id: game_id, result_date: result_dec_date })
        if (data.length <= 0) {

            return res.status(400).json({ success: false, message: "Game result is not decleare yet" })

        } else {

            const open_result_token = data.open_result_token

            if (open_result_token != '') {
                await bid_history_module.updateMany({ open_result_token: open_result_token }, { $set: { pay_status: 0 } })
                await user_notification_module.deleteMany({ userDB_id: result?.userDB_id })
            }
            await game_result_history_module.updateMany({ gameDB_id: game_id, result_date: result_dec_date }, { $set: { open_number: open_number } })

        }
        const result = await game_result_history_module.findOne({ gameDB_id: game_id, result_date: result_dec_date, open_number: { $ne: [0, null] } })
        if (result == null) {
            return res.status(400).json({ success: false, message: "Game result is not decleare yet" })
        } else {
            const open_number = result.open_number
            const open_decleare_status = result.open_decleare_status
            if (open_decleare_status == 1) {
                return res.status(400).json({ success: false, message: "Result already decleared" })
            } else {
                let game_name_result = await games_module.find({ _id: game_id })
                let game_not_name = game_name_result[0].game_name
                let win_number_not = open_number.toString().split("").reduce((acc, curr) => {
                    return acc + Number(curr)
                }, 0)
                if (win_number_not > 9)
                    win_number_not = win_number_not % 10;


                let game_rates = await game_rates_module.find({})

                const single_digit_val_2 = game[0].single_digit_val_2;
                const jodi_digit_val_2 = game[0].jodi_digit_val_2;
                const single_pana_val_2 = game[0].single_pana_val_2;
                const double_pana_val_2 = game[0].double_pana_val_2;
                const tripple_pana_val_2 = game[0].tripple_pana_val_2;
                const half_sangam_val_2 = game[0].half_sangam_val_2;
                const full_sangam_val_2 = game[0].full_sangam_val_2;

                const result = await bid_history_module.aggregate([
                    {
                        $match: {
                            gameDB_id: game_id,
                            pay_status: 0,
                            bid_date: result_dec_date,
                            session: "Open"
                        }
                    },
                    {
                        $lookup: {
                            from: "game",
                            localField: "gameDB_id",
                            foreignField: "_id",
                            as: "game"
                        }
                    },
                    {
                        $unwind: {
                            path: "$game",
                            preserveNullAndEmptyArrays: true
                        }
                    },
                    {
                        $project: {
                            gameName: "$game.game_name",
                            userId: "$userDB_id",
                            userName: "$user.user_name",
                            pana: 1,
                            session: 1,
                            digits: 1,
                            points: 1,
                            bidId: "$_id",
                            bidTxId: 1,
                            pay_status: 1,

                        }

                    }
                ])
                const open_result_token = uniqRandom()

                result.map(async (item) => {

                    if (item.pana == 'Single Digit') {
                        let win_number = open_number.toString().split("").reduce((acc, curr) => {
                            return acc + Number(curr)
                        }, 0)
                        if (win_number > 9)
                            win_number = win_number % 10;

                        if (win_number == item.digits) {
                            win_amt = (single_digit_val_2 / 10) * item.points;


                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';
                            await updateUserBalance(item.user_id, win_amt, msg, open_result_token, item.bid_tx_id);

                            await bid_history_module.updateOne({ bid_id: item.bid_id }, { $set: { pay_status: 1, open_result_token: open_result_token } })
                            await user_notification_module.create({
                                userDB_id: item.userDB_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                            })
                        }
                    } else if (item.pana == 'Triple Pana') {
                        if (open_number == item.digits) {
                            let win_amt = (tripple_pana_val_2 / 10) * item.points;

                            //$msg='Amount won in '.item.game_name.' '.item.pana.' '.item.session.' session for Bid Number- '.item.bid_tx_id;

                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';

                            await updateUserBalance(item.user_id, win_amt, msg, open_result_token, item.bid_tx_id);

                            await bid_history_module.updateOne({ bid_id: item.bid_id }, { $set: { pay_status: 1, open_result_token: open_result_token } })
                            await user_notification_module.create({
                                userDB_id: item.userDB_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                            })
                        }
                    } else if (item.pana == 'Double Pana') {
                        if (open_number == item.digits) {
                            let win_amt = (double_pana_val_2 / 10) * item.points;
                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';
                            updateUserBalance(item.user_id, win_amt, msg, open_result_token, item.bid_tx_id);

                            await bid_history_module.updateOne({ bid_id: item.bid_id }, { $set: { pay_status: 1, open_result_token: open_result_token } })
                            await user_notification_module.create({
                                user_id: item.user_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                open_result_token: open_result_token,
                                bid_tx_id: item.bid_tx_id,
                            })

                        }
                    } else if (item.pana == 'Single Pana') {
                        if (open_number == item.digits) {
                            let win_amt = (single_pana_val_2 / 10) * item.points;

                            //$msg='Amount won in '.item.game_name.' '.item.pana.' '.item.session.' session for Bid Number- '.item.bid_tx_id;
                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';
                            await updateUserBalance(item.user_id, win_amt, msg, open_result_token, item.bid_tx_id);

                            await bid_history_module.updateOne({ bid_id: item.bid_id }, { $set: { pay_status: 1, open_result_token: open_result_token } })
                            await user_notification_module.create({
                                user_id: item.user_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                open_result_token: open_result_token,
                                bid_tx_id: item.bid_tx_id,
                            })
                        }
                    }
                })

                await game_result_history_module.updateMany({ gameDB_id: game_id, open_number: { $ne: [0, null] }, result_date: result_dec_date }, { $set: { open_decleare_status: 1, open_decleare_date: new Date(), open_result_token: open_result_token } })


                return res.status(200).json({ success: true, message: "Open result updated successfully" })
            }

        }


    } catch (error) {
        console.log("error in editOpenResultData", error);
        return res.status(500).json({ success: false, message: error.message })
    }
};

const editCloseResultData = async (req, res) => {
    const { game_id, result_dec_date, close_result, close_number } = req.body
    try {
        const data = await game_result_history_module.findOne({ gameDB_id: game_id, result_date: result_dec_date, })
        if (data.length <= 0) {
            return res.status(400).json({ success: false, msg: "Game result is not decleare yet" })
        } else {

            let close_result_token = data.close_result_token
            if (close_result_token != '') {

                await bid_history_module.updateMany({ close_result_token: close_result_token }, { $set: { pay_status: 0 } })

                //echo "<pre>";print_r($where);die;

                await deductUserCloseWallet(close_result_token);
                await user_notification_module.deleteMany({ close_result_token: close_result_token })

            }
            await game_result_history_module.updateOne({ gameDB_id: game_id, result_date: result_dec_date }, { close_number: close_number })

        }
        const result = await game_result_history_module.findOne({ gameDB_id: game_id, result_date: result_dec_date })
        if (!result) {
            return res.status(400).json({ success: false, msg: "Game result is not decleare yet" })
        } else {

            let close_number = result.close_number;
            let close_decleare_status = result.close_decleare_status;
            if (close_decleare_status == 1) {
                return res.status(400).json({ success: false, msg: "Result already decleared." })
            } else {
                let game_name_result = await games_module.find({ _id: game_id })
                let game_not_name = game_name_result[0].game_name;
                let win_number_not = close_number.toString().split("").reduce((acc, curr) => {
                    return acc + Number(curr)
                }, 0)
                if (win_number_not > 9)
                    win_number_not = win_number_not % 10;

                let game_rate = await game_rates_module.find({})
                const single_digit_val_2 = game_rate[0].single_digit_val_2;
                const jodi_digit_val_2 = game_rate[0].jodi_digit_val_2;
                const single_pana_val_2 = game_rate[0].single_pana_val_2;
                const double_pana_val_2 = game_rate[0].double_pana_val_2;
                const tripple_pana_val_2 = game_rate[0].tripple_pana_val_2;
                const half_sangam_val_2 = game_rate[0].half_sangam_val_2;
                const full_sangam_val_2 = game_rate[0].full_sangam_val_2

                const result = await bid_history_module.aggregate([
                    {
                        $match: {
                            gameDB_id: game_id,
                            pay_status: 0,
                            bid_date: queryDate,
                            session: "Close",
                        },
                    },
                    {
                        $lookup: {
                            from: "games",
                            localField: "gameDB_id",
                            foreignField: "_id",
                            as: "game",
                        },
                    },
                    {
                        $lookup: {
                            from: "users",
                            localField: "userDB_id",
                            foreignField: "_id",
                            as: "user",
                        },
                    },
                    {
                        $unwind: {
                            path: "$game",
                            preserveNullAndEmptyArrays: true,
                        },
                    },
                    {
                        $unwind: {
                            path: "$user",
                            preserveNullAndEmptyArrays: true,
                        },
                    },
                    {
                        $project: {
                            gameName: "$game.game_name",
                            userId: "$userDB_id",
                            userName: "$user.user_name",
                            pana: 1,
                            session: 1,
                            digits: 1,
                            closedigits: 1,
                            points: 1,
                            bidId: "$_id",
                            bidTxId: 1,
                            pay_status: 1,
                            open_result_token: 1,
                        },
                    },

                ])
                const close_result_token = uniqRandom()
                result.map(async (item) => {

                    if (item.pana == 'Single Digit') {
                        let win_number = close_number.toString().split("").reduce((acc, curr) => {
                            return acc + Number(curr)
                        }, 0)
                        if (win_number > 9)
                            win_number = win_number % 10;

                        if (win_number == item.digits) {
                            win_amt = (single_digit_val_2 / 10) * item.points;

                            const message = `${item.gameName} in ${item.pana} (Session-${item.session}) for bid amount-${item.points} Won`
                            await updateUserBalance(item.user_id, win_amt, message, close_result_token, item.bid_tx_id)
                            await user_notification_module.create({
                                user_id: item.user_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                close_result_token: close_result_token,
                                bid_tx_id: item.bid_tx_id,
                            })
                        }
                    } else if (item.pana == 'Triple Pana') {
                        if (close_number == item.digits) {
                            let win_amt = (tripple_pana_val_2 / 10) * item.points;


                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';

                            await updateUserBalance(item.user_id, win_amt, msg, close_result_token, item.bid_tx_id);
                            await user_notification_module.create({
                                user_id: item.user_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                close_result_token: close_result_token,
                                bid_tx_id: item.bid_tx_id

                            })


                        }
                    } else if (item.pana == 'Double Pana') {
                        if (close_number == item.digits) {
                            let win_amt = (double_pana_val_2 / 10) * item.points;

                            //$msg='Amount won in '.item.game_name.' '.item.pana.' '.item.session.' session for Bid Number- '.item.bid_tx_id;

                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';
                            updateUserBalance(item.user_id, win_amt, msg, close_result_token, item.bid_tx_id);

                            await bid_history_module.updateOne({ _id: item.bid_id }, { $set: { pay_status: 1, close_result_token: close_result_token } })


                            await user_notification_module.create({
                                user_id: item.user_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                close_result_token: close_result_token,
                                bid_tx_id: item.bid_tx_id

                            })

                        }
                    } else if (item.pana == 'Single Pana') {
                        if (close_number == item.digits) {
                            let win_amt = (single_pana_val_2 / 10) * item.points;

                            let msg = item.game_name + ' in ' + item.pana + ' ' + '(Session- ' + item.session + ') for bid amount- ' + item.points + ' Won';
                            updateUserBalance(item.user_id, win_amt, msg, close_result_token, item.bid_tx_id);

                            await bid_history_module.updateOne({ _id: item.bid_id }, { $set: { pay_status: 1, close_result_token: close_result_token } })


                            await user_notification_module.create({
                                user_id: item.user_id,
                                message: "Congratulations ,You Won in " + item.game_name + " for Bid Number- " + item.bid_tx_id,
                                close_result_token: close_result_token,
                                bid_tx_id: item.bid_tx_id

                            })
                        }
                    }
                })
                await game_result_history_module.updateMany({
                    close_number: { $ne: [0, null] },
                    gameDB_id: game_id,
                    result_date: result_dec_date
                }, {
                    $set: {
                        close_decleare_status: 1, close_decleare_date: new Date(), close_result_token: close_result_token
                    }

                })
                return res.status(200).json({ success: true, message: "Close result updated successfully" })
            }
        }




        return res.status(200).json({ success: true, msg: "Close result updated successfully" })
    } catch (error) {
        console.log("error in editCloseResultData", error);
        return res.status(500).json({ success: false, msg: error.message })
    }
};

// incomplete function
const ticketHistoryListGridData = async (req, res) => {
    try {
        const columns = [
            '_id',
            'txn_id',
            'username',
            'lottery_name',
            'ticket_num',
            'amount',
            'date',
        ];

        const limit = parseInt(req.body.length) || 10;
        const start = parseInt(req.body.start) || 0;
        const orderCol = parseInt(req.body.order?.[0]?.column || 0);
        const orderField = columns[orderCol] || 'bid_id';
        const orderDir = req.body.order?.[0]?.dir === 'asc' ? 1 : -1;
        const search = req.body.search?.value || '';

        let filter = {};
        if (search) {
            filter = {
                $or: [
                    { lottery_name: { $regex: `^${search}`, $options: 'i' } },
                    { open_date: { $regex: `^${search}`, $options: 'i' } },
                    { close_date: { $regex: `^${search}`, $options: 'i' } }
                ]
            };
        }

        const totalData = await lottery_bid_history_module.countDocuments({});
        const totalFiltered = await lottery_bid_history_module.countDocuments(filter);

        const records = await lottery_bid_history_module
            .find(filter)
            .sort({ [orderField]: orderDir })
            .skip(start)
            .limit(limit)
            .lean();

        const data = await Promise.all(records.map(async (rs, index) => {
            const user = await User.findOne({ user_id: rs.user_id }).lean();
            const username = user ? user.user_name.toUpperCase() : 'UNKNOWN';

            return {
                '#': start + index + 1,
                bid_id: rs.bid_id,
                user_id: rs.user_id,
                username: `<a href="${process.env.BASE_URL}/admin/view-user/${rs.user_id}">${username}</a>`,
                ticket_num: rs.ticket_num,
                txn_id: rs.bid_tx_id,
                amount: rs.points,
                date: rs.insert_date,
                lottery_name: rs.lottery_name?.toUpperCase() || ''
            };
        }));

        res.json({
            draw: parseInt(req.body.draw) || 1,
            recordsTotal: totalData,
            recordsFiltered: totalFiltered,
            data
        });
    } catch (err) {
        console.error("ticketHistoryListGridData Error:", err);
        res.status(500).json({
            status: 'error',
            msg: 'Internal server error'
        });
    }
};

// incomplete function
const lotteryResultListLoadData = async (req, res) => {
    try {
        const { date } = req.body;

        const results = await GameResultHistory.find({ result_date: date });

        const response = results.map((doc, index) => ({
            sn: index + 1,
            game_name: doc.game_name,
            result_date: doc.result_date,
            open_date: doc.open_date,
            close_date: doc.close_date,
            open_result: doc.open_result,
            close_result: doc.close_result
        }));

        res.json(response);
    } catch (error) {
        console.error("Error fetching game result history:", error);
        res.status(500).json({ error: 'Something went wrong' });
    }
}

// incomplete function
const getLotteryListForResult = (req, res) => {
    res.send('get-lottery-list-for-result route is working!');
}

// incomplete function
const getDecleareLotteryData = (req, res) => {
    res.send('get-decleare-lottery-data route is working!');
}

// incomplete function
const saveLotteryData = (req, res) => {
    res.send('save-lottery-data route is working!');
}

// incomplete function
const decleareLotteryData = (req, res) => {
    res.send('decleare-lottery-data route is working!');
}

// incomplete function
const getLotteryWinnerList = (req, res) => {
    res.send('get-lottery-winner-list route is working!');
}

const checkOpenMarketResultDeclaration = async (req, res) => {
    try {
        const gameDB_id = req?.body?.gameDB_id?.trim() || '';
        const result_date = req?.body?.result_date?.trim() || '';

        if (!gameDB_id || !result_date) {
            return res.status(400).json({
                success: false,
                msg: "gameDB_id & result_date is required."
            });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id.",
            });
        }

        const where = { gameDB_id, result_date };

        const results = await admin_module.find(where);

        let open_declare_status = 0;
        let open_number = 0;

        if (results.length > 0) {
            results.forEach(rs => {
                open_declare_status = rs.open_declare_status;
                open_number = rs.open_number;
            });
        }

        res.json({
            success: true,
            open_declare_status,
            open_number
        });
    } catch (error) {
        console.error(error);
        res.status(500).json({ success: false, error: 'Internal Server Error' });
    }
};

// ---------------- Starline Game Section ----------------

const editStarlineGame = async (req, res) => {
    try {
        const gameDB_id = req?.params?.gameDB_id || "";

        if (!gameDB_id || !mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id.",
            });
        }

        const result = await starline_games_module.findOne({ gameDB_id });

        if (!result) {
            return res.status(404).json({ success: false, msg: "Game not found" });
        }

        const data = {
            gameDB_id: result.gameDB_id,
            game_name: result.game_name,
            game_name_hindi: result.game_name_hindi,
            open_time: convert12To24(result.open_time),
            close_time: convert12To24(result.close_time)
        };

        res.json({
            success: true,
            data
        })
        // res.render('admin/q1', data);
    } catch (err) {
        console.error("Error in editgame:", err);
        res.status(500).send("Internal Server Error");
    }
}

// Starline Bid History
const starlineUserBidHistory = async (req, res) => {
    try {
        const adminData = req?.user || null;

        console.log(`(((((((()))))) ~ adminController.js:13225 ~ updatePassword ~ adminData:`, adminData);

        console.log(`(((((((()))))) ~ adminController.js:13225 ~ updatePassword ~ adminData:`, adminData);

        console.log(`(((((((()))))) ~ adminController.js:13225 ~ updatePassword ~ adminData:`, adminData);

        console.log(`(((((((()))))) ~ adminController.js:13225 ~ updatePassword ~ adminData:`, adminData);

        console.log(`(((((((()))))) ~ adminController.js:13225 ~ updatePassword ~ adminData:`, adminData);

        console.log(`(((((((()))))) ~ adminController.js:13225 ~ updatePassword ~ adminData:`, adminData);
        if (!adminData) {
            return res.status(404).json({ success: false, msg: 'User not found' })
        }

        if (adminData?.admin_type === 1 || adminData?.admin_type === 2) {
            const game_result = await games_module.find({ status: 1 });

            return res.json({
                success: true,
                title: "Bid History Management",
                banner_title: "Bid History Management",
                banner_title2: "Bid History",
                active_menu: "user_bid_history",
                game_result
            })

            // res.render('admin/s1', {
            //     title: "Bid History Management",
            //     banner_title: "Bid History Management",
            //     banner_title2: "Bid History",
            //     active_menu: "user_bid_history",
            //     game_result
            // });
        } else {
            return res.json({
                success: true,
                msg: "redirect to /admin"
            })
            // res.redirect('/admin');
        }

    } catch (error) {
        console.error("Error in userBidHistory:", error);
        res.status(500).json({ success: false, msg: "Internal Server Error" });
    }
}

const deleteOpenStarlineResultData = async (req, res) => {
    try {
        let { gameDB_id, result_dec_date } = req?.body || {};
        gameDB_id = toStr(gameDB_id)
        result_dec_date = toStr(result_dec_date)

        if (!gameDB_id || !result_dec_date) {
            return res.status(400).json({
                success: false,
                msg: 'Missing required fields.'
            });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id.",
            });
        }

        const trimmedDate = result_dec_date.trim();

        const result = await game_result_history_module.findOne({
            gameDB_id,
            result_date: trimmedDate
        });

        if (result) {
            return res.json({
                success: false,
                msg: error("Game result is not declared yet")
            });
        }

        const open_result_token = result.open_result_token;

        await bid_history_module.updateMany(
            { open_result_token },
            { $set: { pay_status: 0 } }
        );

        await deductUserWallet(open_result_token);

        await game_result_history_module.deleteMany({ open_result_token: open_result_token });
        await user_notification_module.deleteMany({ open_result_token: open_result_token });

        return res.json({
            success: true,
            msg: success("Result Successfully deleted.")
        });

    } catch (err) {
        console.error("Error in deleteOpenResultData:", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error"
        });
    }
};

// incomplete function
// Export Option Bid History Data
const exportOptionGalidisswarBidHistoryData = (req, res) => {
    // TODO: export Galidisswar bid history data (CSV, XLS, etc.)
    res.send('export-option-galidisswar-bid-history-data route is working!');
};

const updateGaliDissawarBid = async (req, res) => {
    try {
        const { digits = "", bidDB_id = "", market_status = "" } = req?.body || {};

        if (!digits || !bidDB_id || !market_status) {
            return res.status(400).json({ success: false, msg: 'Missing required fields.' })
        }

        if (!mongoose.isValidObjectId(bidDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid bidDB_id.",
            });
        }

        const updateResult = await gali_disswar_bid_history_module.updateOne(
            { _id: bidDB_id },
            { $set: { digits: digits } }
        );

        if (updateResult.matchedCount === 0) {
            return res.status(404).json({ success: false, msg: 'Bid not found.' });
        }

        const data = {
            success: true,
            digit: digits,
            msg: 'Bid updated successfully.'
        };

        res.json(data);
    } catch (error) {
        console.error("Error updating bid:", error);
        res.status(500).json({ success: false, msg: 'Internal server error.' });
    }
};

const getOpenData = async (req, res) => {
    let { open_number = "" } = req?.body || {};
    open_number = Number(toStr(open_number))

    if (!open_number) {
        return res.status(400).json({ success: false, msg: 'Invalid open_number' });
    }

    const open_num =
        parseInt(open_number[0]) +
        parseInt(open_number[1]) +
        parseInt(open_number[2]);

    let open_result = open_num < 10 ? open_num : open_num % 10;

    res.json({
        success: true,
        open_result: open_result
    });
};

const getCloseData = (req, res) => {
    let { close_number = "" } = req?.body || {};
    close_number = Number(toStr(close_number))

    if (!close_number) {
        return res.status(400).json({ success: false, msg: 'Invalid close_number' });
    }

    const close_num =
        parseInt(close_number[0]) +
        parseInt(close_number[1]) +
        parseInt(close_number[2]);

    let close_result = close_num < 10 ? close_num : close_num % 10;

    res.json({
        success: true,
        close_result: close_result
    });
};

const deleteOpenGalidisswarResultData = async (req, res) => {
    try {
        let { gameDB_id = "", result_dec_date = "" } = req?.body || {};

        gameDB_id = toStr(gameDB_id)
        result_dec_date = toStr(result_dec_date)

        if (!gameDB_id || !result_dec_date) {
            return res.status(400).json({ success: false, msg: 'Missing required fields' });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id.",
            });
        }

        let start = new Date(new Date(result_dec_date).setHours(0, 0, 0, 0))
        let end = new Date(new Date(result_dec_date).setHours(23, 59, 59, 999))

        const results = await gali_disswar_game_result_history_module.find({
            gameDB_id,
            result_date: {
                $and: [
                    { $gt: start },
                    { $lt: end }
                ]
            }
        }).lean();

        if (results.length === 0) {
            return res.json({
                success: false,
                msg: errorMsg('Game result is not declared yet')
            });
        }

        const openResultToken = results[results.length - 1].open_result_token;

        if (openResultToken) {
            await gali_disswar_bid_history_module.updateMany(
                { open_result_token: openResultToken },
                { $set: { pay_status: 0 } }
            );

            await deductUserWallet(openResultToken);

            await Promise.all([
                gali_disswar_game_result_history_module.deleteMany({ open_result_token: openResultToken }),
                user_notification_module.deleteMany({ open_result_token: openResultToken })
            ]);
        }

        return res.json({
            status: 'success',
            msg: 'Result successfully deleted.'
        });
    } catch (err) {
        console.error('deleteOpenResultData error:', err);
        return res.status(500).json({
            success: false,
            msg: 'Internal server error'
        });
    }
};

const galidisswarResultHistoryListGridData = async (req, res) => {
    try {
        const fields = [
            "gameDB_id.game_name",   // 0 - Note: changed to dot notation for aggregation
            "result_date",           // 1
            "close_decleare_date",   // 2
            "close_number"           // 3
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 0;
        const fieldIndex = parseInt(req.body.fieldIndex) || 0;
        const orderField = fields[fieldIndex] || "result_date";
        const orderDir = req?.body?.order === 1 ? 1 : -1;

        const searchValue = req.body.searchValue?.trim() || '';
        const isNumeric = !isNaN(searchValue);
        const regexValue = `^${searchValue}`;
        const skip = !searchValue ? (page - 1) * limit : 0;

        // Aggregation pipeline
        const pipeline = [
            {
                $lookup: {
                    from: "gali_disswar_games",
                    localField: "gameDB_id",
                    foreignField: "_id",
                    as: "gameDB_id"
                }
            },
            {
                $unwind: {
                    path: "$gameDB_id",
                    preserveNullAndEmptyArrays: true
                }
            },
        ];

        // Search stage
        if (searchValue) {
            if (isNumeric) {
                pipeline.push({
                    $match: {
                        $expr: {
                            $regexMatch: {
                                input: { $toString: "$close_number" },
                                regex: regexValue,
                                options: "i"
                            }
                        }
                    }
                });
            } else {
                pipeline.push({
                    $match: {
                        "gameDB_id.game_name": {
                            $regex: regexValue,
                            $options: "i"
                        }
                    }
                });
            }
        }

        // Count total filtered
        const totalFilteredAgg = await gali_disswar_game_result_history_module.aggregate([...pipeline, { $count: "total" }]);
        const totalFiltered = totalFilteredAgg[0]?.total || 0;

        // Sorting
        pipeline.push({
            $sort: {
                [orderField]: orderDir
            }
        });

        // Pagination
        pipeline.push({ $skip: skip });
        pipeline.push({ $limit: limit });

        // Projection
        pipeline.push({
            $project: {
                _id: 1,
                result_date: 1,
                close_decleare_date: 1,
                close_number: 1,
                "game_name": "$gameDB_id.game_name"
            }
        });

        // Execute aggregation
        const results = await gali_disswar_game_result_history_module.aggregate(pipeline);

        // Format result
        const data = results.map((rs) => {
            const closeNum = rs.close_number?.toString() || '';
            const sumMod = closeNum
                ? closeNum.split("").reduce((acc, digit) => acc + Number(digit), 0) % 10
                : '';

            return {
                _id: rs._id,
                game_name: rs.game_name || 'N/A',
                result_date: formatDateToDDMMYYYY(rs.result_date),
                close_decleare_date: rs?.close_decleare_date
                    ? formatDateToDDMMYYYY(rs.close_decleare_date)
                    : 'N/A',
                close_number: `${rs.close_number}-${sumMod}`
            };
        });

        res.json({
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error(err);
        res.status(500).json({ success: false, error: 'Something went wrong' });
    }
};

const ideasListGridData = async (req, res) => {
    try {
        const fields = [
            "userDB_id.user_name", // Sortable field
            "ideas",               // Sortable field
            "insert_date",         // Sortable field
        ];

        const limit = parseInt(req.body.length) || 10;
        const page = parseInt(req.body.start) || 0;
        const fieldIndex = parseInt(req.body.fieldIndex) || 0;
        const orderField = fields[fieldIndex] || "insert_date";
        const orderDir = req?.body?.order === 1 ? 1 : -1;

        const searchValue = req.body.searchValue?.trim() || "";
        const isNumeric = !isNaN(searchValue);
        const regex = new RegExp(`^${searchValue}`, "i");
        const skip = !searchValue ? (page - 1) * limit : 0;

        // Base pipeline
        const pipeline = [
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userDB_id"
                }
            },
            {
                $unwind: {
                    path: "$userDB_id",
                    preserveNullAndEmptyArrays: true
                }
            },
        ];

        // Conditional search
        if (searchValue && !isNumeric) {
            pipeline.push({
                $match: {
                    $or: [
                        { "userDB_id.user_name": { $regex: regex } },
                        { ideas: { $regex: regex } }
                    ]
                }
            });
        }

        // Clone pipeline for counting totalFiltered
        const totalFilteredAgg = await ideas_module.aggregate([
            ...pipeline,
            { $count: "total" }
        ]);
        const totalFiltered = totalFilteredAgg[0]?.total || 0;

        // Append sorting, pagination, and projection
        pipeline.push(
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit },
            {
                $project: {
                    _id: 1,
                    ideas: 1,
                    userDB_id: '$userDB_id._id',
                    insert_date: 1,
                    user_name: "$userDB_id.user_name"
                }
            }
        );

        // Final data fetch
        const results = await ideas_module.aggregate(pipeline);

        // Format insert_date
        const data = results.map((rs) => ({
            ...rs,
            insert_date: formatDateToDDMMYYYY(rs.insert_date)
        }));

        res.json({
            recordsFiltered: totalFiltered,
            data,
            limit
        });

    } catch (err) {
        console.error("ideasListGridData error:", err);
        res.status(500).json({ success: false, error: "Something went wrong" });
    }
};

const deleteIdea = async (req, res) => {
    try {
        const { ideaDB_id } = req.params;

        // Validate ObjectId
        if (!ideaDB_id || !mongoose.isValidObjectId(ideaDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid or missing ideaDB_id.",
            });
        }

        const deleted = await ideas_module.findByIdAndDelete(ideaDB_id);

        if (!deleted) {
            return res.status(404).json({
                success: false,
                msg: "Idea not found or already deleted.",
            });
        }

        res.json({
            success: true,
            msg: "Idea deleted successfully.",
            deletedId: ideaDB_id
        });

    } catch (err) {
        console.error("deleteIdea error:", err);
        res.status(500).json({ success: false, msg: "Something went wrong" });
    }
};


const addGamesTime = async (req, res) => {
    try {
        const {
            games_time_id,
            seridevi_open_time,
            seridevi_close_time,
            madhur_m_open_time,
            madhur_m_close_time,
            gold_d_open_time,
            gold_d_close_time,
            madhur_d_open_time,
            madhur_d_close_time,
            super_milan_open,
            super_milan_close,
            rajdhani_d_open,
            rajdhani_d_close,
            supreme_d_open,
            supreme_d_close,
            sridevi_night_open,
            sridevi_night_close,
            gold_night_open,
            gold_night_close,
            madhure_night_open,
            madhure_night_close,
            supreme_night_open,
            supreme_night_close,
            rajhdhani_night_open,
            rajhdhani_night_close
        } = req.body;

        const insertData = {
            sridevi_open_time: get12HoursTimeFromISO(seridevi_open_time),
            sridevi_close_time: get12HoursTimeFromISO(seridevi_close_time),
            madhur_morning_open_time: get12HoursTimeFromISO(madhur_m_open_time),
            madhur_morning_close_time: get12HoursTimeFromISO(madhur_m_close_time),
            gold_day_open_time: get12HoursTimeFromISO(gold_d_open_time),
            gold_day_close_time: get12HoursTimeFromISO(gold_d_close_time),
            madhur_day_open_time: get12HoursTimeFromISO(madhur_d_open_time),
            madhur_day_close_time: get12HoursTimeFromISO(madhur_d_close_time),
            super_milan_open_time: get12HoursTimeFromISO(super_milan_open),
            super_milan_close_time: get12HoursTimeFromISO(super_milan_close),
            rajdhani_day_open_time: get12HoursTimeFromISO(rajdhani_d_open),
            rajdhani_day_close_time: get12HoursTimeFromISO(rajdhani_d_close),
            supreme_day_open_time: get12HoursTimeFromISO(supreme_d_open),
            supreme_day_close_time: get12HoursTimeFromISO(supreme_d_close),
            sri_devi_night_open_time: get12HoursTimeFromISO(sridevi_night_open),
            sri_devi_night_close_time: get12HoursTimeFromISO(sridevi_night_close),
            gold_night_open_time: get12HoursTimeFromISO(gold_night_open),
            gold_night_close_time: get12HoursTimeFromISO(gold_night_close),
            madhur_night_open_time: get12HoursTimeFromISO(madhure_night_open),
            madhur_night_close_time: get12HoursTimeFromISO(madhure_night_close),
            supreme_night_open_time: get12HoursTimeFromISO(supreme_night_open),
            supreme_night_close_time: get12HoursTimeFromISO(supreme_night_close),
            rajdhani_night_open_time: get12HoursTimeFromISO(rajhdhani_night_open),
            rajdhani_night_close_time: get12HoursTimeFromISO(rajhdhani_night_close)
        };

        let response = {};

        if (!games_time_id) {
            // await game_name_module.create(insertData);
            response.success = true;
            response.msg = "Games times successfully inserted.";
        } else {
            // await game_name_module.findByIdAndUpdate(games_time_id, insertData);
            response.success = true;
            response.msg = "Games times successfully updated.";
        }

        res.json(response);
    } catch (error) {
        console.error(error);
        res.status(500).json({ success: false, msg: "Internal server error" });
    }
};

const changeGameTime = async (req, res) => {
    try {
        let { gameDB_id = "", open_time = "", close_time = "" } = req?.body || {};

        gameDB_id = toStr(gameDB_id)
        open_time = toStr(open_time)
        close_time = toStr(close_time)

        if (!gameDB_id || !open_time || !close_time) {
            return res.status(400).json({ success: false, msg: 'Missing required fields' });
        }

        if (!mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({
                success: false,
                msg: "Invalid gameDB_id.",
            });
        }

        const data = {
            open_time: getISOFrom12HoursTime(open_time),
            open_time_sort: getISOFrom12HoursTime(open_time),
            close_time: open_time(close_time)
        };

        // const result = await game_name_module.findOneAndUpdate(
        //     { _id: gameDB_id },
        //     data,
        //     { new: true }
        // );

        return res.json({
            success: true,
            msg: "Game time successfully updated.",
            data: result
        });
    } catch (error) {
        console.error("Error updating game time:", error);
        return res.status(500).json({
            success: false,
            msg: "Something went wrong while updating game time."
        });
    }
};

const tinymceUploadImage = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        if (!req.file || !req.file.buffer || !req.file.mimetype) {
            return res.status(400).json({ success: false, msg: 'Valid file is required' });
        }

        const image = new file_module({
            fileBuffer: req.file.buffer,
            content_type: req.file.mimetype
        });

        const savedImage = await image.save();

        const fullUrl = `${baseUrl}/file/uploads/images/${savedImage._id.toString()}`

        res.json({ success: true, location: fullUrl });
    } catch (err) {
        console.error('Upload error:', err);
        res.status(500).json({ success: false, msg: 'Server Error' });
    }
};

// incomplete function
const exportOptionBidHistoryData = async (req, res) => {
    try {
        const { bid_date = "", gameDB_id = "", game_type = "" } = req?.body || {};

        const gameTypeMap = {
            1: 'Single Digit',
            2: 'Jodi Digit',
            3: 'Single Pana',
            4: 'Double Pana',
            5: 'Triple Pana',
            6: 'Half Sangam',
            7: 'Full Sangam'
        };

        const type = gameTypeMap[game_type];

        let ISODate = convertToISODate(bid_date)

        let start = ISODate.setHours(0, 0, 0, 0)
        let end = ISODate.setHours(23, 59, 59, 999)

        let query = {
            bid_date: {
                $and: [
                    { $gt: start },
                    { $lt: end }
                ]
            },
            gameDB_id,
            pana: game_type
        };

        const results = await bid_history_module.find(query)
            .populate({ path: 'userDB_id', select: 'user_name' })
            .lean();

        for (const rs of results) {
            rs['User Name'] = rs.userDB_id?.user_name || 'N/A';
            rs['Game Name'] = rs.game_name;

            if (rs.pana === 'Single Digit') {
                if (rs.session === 'Open') {
                    rs.Open_Digit = rs.digits;
                    rs.Close_Digit = 'N/A';
                    rs.Open_Pana = 'N/A';
                    rs.Close_Pana = 'N/A';
                } else {
                    rs.Open_Digit = 'N/A';
                    rs.Close_Digit = rs.digits;
                    rs.Open_Pana = 'N/A';
                    rs.Close_Pana = 'N/A';
                }
            }

            if (['Jodi Digit', 'Red Bracket', 'Group Jodi'].includes(rs.pana)) {
                rs.Open_Digit = rs.digits[0];
                rs.Close_Digit = parseInt(rs.digits) % 10;
                rs.Open_Pana = 'N/A';
                rs.Close_Pana = 'N/A';
            }

            if (['Single Pana', 'Double Pana', 'Triple Pana', 'SP', 'DP', 'TP'].includes(rs.pana)) {
                const digitSum = parseInt(rs.digits[0]) + parseInt(rs.digits[1]) + parseInt(rs.digits[2]);
                const totalDigit = digitSum % 10;

                if (rs.session === 'Open') {
                    rs.Open_Digit = totalDigit;
                    rs.Close_Digit = 'N/A';
                    rs.Open_Pana = rs.digits;
                    rs.Close_Pana = 'N/A';
                } else {
                    rs.Open_Digit = 'N/A';
                    rs.Close_Digit = totalDigit;
                    rs.Open_Pana = 'N/A';
                    rs.Close_Pana = rs.digits;
                }
            }

            if (rs.pana === 'Half Sangam') {
                if (rs.session === 'Open') {
                    rs.Open_Digit = rs.digits;
                    rs.Close_Digit = 'N/A';
                    rs.Open_Pana = 'N/A';
                    rs.Close_Pana = rs.closedigits;
                } else {
                    rs.Open_Digit = 'N/A';
                    rs.Close_Digit = rs.digits;
                    rs.Open_Pana = rs.closedigits;
                    rs.Close_Pana = 'N/A';
                }
            }

            if (rs.pana === 'Full Sangam') {
                rs.Open_Digit = 'N/A';
                rs.Close_Digit = 'N/A';
                rs.Open_Pana = rs.digits;
                rs.Close_Pana = rs.closedigits;
            }

            // Clean up
            delete rs.digits;
            delete rs.closedigits;
            delete rs.user_id;
        }

        const fileName = `Bid_History_Data_${moment().format('YYYY-MM-DD_HH_mm_ss')}.xls`;
        const filePath = path.join(__dirname, '../temp', fileName);
        const xls = json2xls(results);

        fs.writeFileSync(filePath, xls, 'binary');

        res.download(filePath, fileName, (err) => {
            if (err) {
                console.error('Download error:', err);
            }
            fs.unlink(filePath, () => { }); // cleanup temp file
        });

    } catch (error) {
        console.error('Export error:', error);
        res.status(500).json({ message: 'Something went wrong during export' });
    }
};

const mainMarketReport = async (req, res) => {
    try {
        const startDate = new Date(req?.body?.start_date);
        const endDate = new Date(req?.body?.end_date);
        const marketStatus = req?.body?.market_status;
        const gameName = req?.body?.game_name;
        const gameType = req?.body?.game_type;
        const digit = parseInt(req?.body?.digit);

        const matchStage = {
            bid_date: {
                $gte: startDate,
                $lte: endDate
            },
            game_id: gameName,
            pana: gameType,
            session: marketStatus
        };

        if (marketStatus === "Open") {
            matchStage.digits = digit;
        } else {
            matchStage.closedigits = digit;
        }

        const result = await tb_bid_history.aggregate([
            {
                $match: matchStage
            },
            {
                $lookup: {
                    from: "tb_user",
                    localField: "user_id",
                    foreignField: "user_id",
                    as: "user_info"
                }
            },
            {
                $unwind: {
                    path: "$user_info",
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $project: {
                    bid_id: 1,
                    game_name: 1,
                    digits: 1,
                    session: 1,
                    closedigits: 1,
                    user_name: "$user_info.user_name",
                    pana: 1,
                    bid_date: 1,
                    points: 1
                }
            }
        ]);

        let i = 1;
        let listdata = "";

        result.forEach((rs) => {
            let single_ank;
            if (rs.pana === "Single Digit" && rs.session === "Open") {
                single_ank = rs.digits;
            } else if (
                ["Double Pana", "Single Pana", "Triple Pana"].includes(rs.pana) &&
                rs.session === "Open"
            ) {
                const a = rs.digits % 10;
                const b = Math.floor(rs.digits / 10);
                const c = b % 10;
                const d = Math.floor(rs.digits / 100);
                const e = a + c + d;
                single_ank = e % 10;
            } else if (rs.pana === "Single Digit" && rs.session === "Close") {
                single_ank = rs.closedigits;
            } else if (
                ["Double Pana", "Half Sangam", "Single Pana", "Triple Pana"].includes(rs.pana) &&
                rs.session === "Close"
            ) {
                const a = rs.closedigits % 10;
                const b = Math.floor(rs.closedigits / 10);
                const c = b % 10;
                const d = Math.floor(rs.closedigits / 100);
                const e = a + c + d;
                single_ank = e % 10;
            }

            const pana = rs.session === "Open" ? rs.digits : rs.closedigits;
            const action = `<a title="Edit" href="javascript:void(0);" data-href="/admin/edit-bid/${rs.bid_id}" class="openpopupeditbid"><button class="btn btn-outline-primary btn-xs m-l-5" type="button" title="edit">Edit</button></a>`;

            listdata += `<tr><td>${i}</td><td>${rs.user_name || "-"}</td><td>${rs.game_name}</td><td>${rs.pana}</td><td>${single_ank}</td><td>${pana}</td><td>${rs.points}</td><td>${new Date(rs.bid_date).toISOString().split("T")[0]}</td><td>${action}</td></tr>`;
            i++;
        });

        return res.json({ listdata });

    } catch (error) {
        console.error("Error in mainMarketReport:", error);
        return res.status(500).json({ error: "Internal Server Error" });
    }
};

const showDigit = async (req, res) => {
    const { game_type } = req.body;
    let result = [];

    try {
        switch (game_type) {
            case 'Single Digit':
                result = await SingleDigit.find({}, { _id: 0, id: 1, single_digit: 1 }).lean();
                result = result.map(r => ({ numbers: r.single_digit }));
                break;
            case 'Full Sangam':
                result = await FullSangam.find({}).lean();
                break;
            case 'Jodi Digit':
                result = await JodiDigit.find({}, { _id: 0, id: 1, jodi_digit: 1 }).lean();
                result = result.map(r => ({ numbers: r.jodi_digit }));
                break;
            case 'Double Pana':
                result = await DoublePana.find({}).lean();
                break;
            case 'Half Sangam':
                result = await HalfSangam.find({}).lean();
                break;
            case 'Single Pana':
                result = await SinglePana.find({}).lean();
                break;
            case 'Triple Pana':
                result = await TriplePana.find({}).lean();
                break;
            default:
                break;
        }

        // Create options for dropdown
        let options = "<option value=''>--Select Digit--</option>";
        result.forEach(r => {
            const val = r.numbers || r.number || r.value || r.digit || r.single_digit || r.jodi_digit || '';
            options += `<option value="${val}">${val}</option>`;
        });

        res.json({ result: options });
    } catch (error) {
        console.error('Error in /show-digit:', error);
        res.status(500).json({ error: 'Internal Server Error' });
    }
};

const resultHistoryListGridData = async (req, res) => {
    const columns = ['id', 'game_id', 'result_date', 'open_decleare_date', 'close_decleare_date', 'open_number', 'close_number'];

    const limit = parseInt(req.body.length) || 10;
    const start = parseInt(req.body.start) || 0;
    const orderColIndex = req.body.order?.[0]?.column || 0;
    const order = columns[orderColIndex] || 'result_date';
    const dir = req.body.order?.[0]?.dir === 'desc' ? -1 : 1;
    const search = req.body.search?.value || '';

    const matchStage = search
        ? {
            $or: [
                { result_date: { $regex: search, $options: 'i' } },
                { game_id: { $regex: search, $options: 'i' } }
            ]
        }
        : {};

    const pipeline = [
        { $match: matchStage },
        {
            $lookup: {
                from: 'games',
                localField: 'game_id',
                foreignField: 'game_id',
                as: 'game'
            }
        },
        { $unwind: '$game' },
        { $sort: { [order]: dir } },
        { $skip: start },
        { $limit: limit }
    ];

    const countTotal = await ResultHistory.countDocuments({});
    const countFiltered = await ResultHistory.countDocuments(matchStage);

    const records = await ResultHistory.aggregate(pipeline);

    const data = records.map((record, index) => {
        const openNumber = record.open_number || '';
        const closeNumber = record.close_number || '';

        const openSum = openNumber ? openNumber[0] * 1 + openNumber[1] * 1 + openNumber[2] * 1 : null;
        const closeSum = closeNumber ? closeNumber[0] * 1 + closeNumber[1] * 1 + closeNumber[2] * 1 : null;

        let open_result = '<span class="sub_s td_color_1">***</span><span class="hyphen">-</span><span class="sub_s td_color_1">*</span>';
        if (openNumber) {
            const resultDigit = openSum % 10;
            const className = record.open_decleare_status === 0 ? 'td_color_1' : 'td_color_2';
            open_result = `<span class="${className}">${openNumber}-${resultDigit}</span>`;
        }

        let close_result = '<span class="sub_s td_color_1">*</span><span class="hyphen">-</span><span class="sub_s td_color_1">***</span>';
        if (closeNumber) {
            const resultDigit = closeSum % 10;
            const className = record.close_decleare_status === 0 ? 'td_color_1' : 'td_color_2';
            close_result = `<span class="${className}">${resultDigit}-${closeNumber}</span>`;
        }

        return {
            '#': start + index + 1,
            game_name: record.game.game_name,
            result_date: new Date(record.result_date).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }),
            open_date: record.open_decleare_date
                ? new Date(record.open_decleare_date).toLocaleString('en-GB')
                : 'N/A',
            close_date: record.close_decleare_date
                ? new Date(record.close_decleare_date).toLocaleString('en-GB')
                : 'N/A',
            open_result,
            close_result
        };
    });

    return res.json({
        draw: parseInt(req.body.draw) || 1,
        recordsTotal: countTotal,
        recordsFiltered: countFiltered,
        data
    });
};


// Save Close Data
const saveCloseData = async (req, res) => {
    const { game_id, close_number, result_dec_date } = req.body
    const result = await game_result_history_module.findOne({ gameDB_id: game_id, result_date: result_dec_date })
    if (result == null) {
        return res.status(400).json({ success: false, message: "Game result is not decleare yet" })
    } else {

        let open_decleare_status = 0;
        let close_decleare_status = 0;
        if (result != null) {
            open_decleare_status = result.open_decleare_status;
            close_decleare_status = result.close_decleare_status;

        }
        if (close_decleare_status == 1) {
            return res.status(400).json({ success: false, message: "Result already decleared" })
        } else {
            if (result == null) {
                return res.status(400).json({ success: false, message: "Please Declare Open Result First" })
            } else {
                if (open_decleare_status == 1) {
                    let close_num = close_number.split("").reduce((acc, curr) => {
                        return acc + Number(curr)
                    }, 0)
                    res.status(200).json({ success: true, message: "Successfully Saved.", data: close_num < 10 ? close_num : close_num % 10 })
                } else {
                    return res.status(400).json({ success: false, message: "Please Declare Open Result First." })
                }
            }


        }


    }

};
// Open Result Notification Continuously
const openResultNotificationContinously = async (req, res) => {

    const {
        game_not_name,
        open_number,
        win_number_not
    } = req.body
    try {
        const user = await user_module.find({ notification_status: 1 })
        user.map(async (item) => {
            const user_id = item._id
            const data = await player_ids_module.find({ user_id: user_id })
            let player_id = ""
            data.map(async (item) => {
                player_id += ","
                player_id += item.player_id
            })
            playerIdList = playerIdList.replace(/^,|,$/g, '');

            const to = playerIdList;
            const array = [];
            array.push(to);
            let notice_title = game_not_name;
            let notification_content = open_number + '-' + win_number_not;
            // await sendNotification(to, notice_title, notification_content, "1")
        })
        return res.status(200).json({ success: true, message: "Open result notification sent successfully" })
    } catch (error) {
        console.log("error in openResultNotificationContinously", error);
        return res.status(500).json({ success: false, message: error.message })

    }


};



// Get Open Winner List
const getOpenWinnerList_starline = async (req, res) => {

    const { game_id, result_dec_date } = req.body
    try {

        const data = await starline_game_result_history_module.find(
            {
                gameDB_id: game_id,
                opne_number: { $ne: [0, null] },
                result_date: result_dec_date
            }
        )
        let data_array

        let win_amt_sum = 0;
        let points_amt_sum = 0;
        data.map(async (item) => {

            const starline_rate = await starline_game_rates_module.find({})
            let open_number = item.open_number
            starline_rate.map(async (item) => {
                const single_digit_val_2 = item.single_digit_val_2;
                const single_pana_val_2 = item.single_pana_val_2;
                const double_pana_val_2 = item.double_pana_val_2;
                const tripple_pana_val_2 = item.tripple_pana_val_2;
                const single_digit_val_1 = item.single_digit_val_1;
                const single_pana_val_1 = item.single_pana_val_1;
                const double_pana_val_1 = item.double_pana_val_1;
                const tripple_pana_val_1 = item.tripple_pana_val_1;

                const data = await starline_bid_history_module.aggregate([
                    {
                        $match: {
                            gameDB_id: game_id,
                            pay_status: 0,
                            bid_date: result_dec_date,
                            session: "Open"
                        }
                    }, {
                        $lookup: {
                            from: "games",
                            localField: "gameDB_id",
                            foreignField: "_id",
                            as: "game"
                        }
                    },
                    {
                        $lookup: {
                            from: "users",
                            localField: "userDB_id",
                            foreignField: "_id",
                            as: "user",
                        },
                    },
                    {
                        $unwind: {
                            path: "$game",
                            preserveNullAndEmptyArrays: true,
                        },
                    },
                    {
                        $unwind: {
                            path: "$user",
                            preserveNullAndEmptyArrays: true,
                        },
                    },
                    {
                        $project: {
                            gameName: "$game.game_name",
                            userId: "$user._id",
                            userName: "$user.user_name",
                            pana: 1,
                            session: 1,
                            digits: 1,
                            closedigits: 1,
                            points: 1,
                            bidId: "$_id",
                            bidTxId: 1,
                            pay_status: 1,
                            open_result_token: 1,
                        },
                    },
                ])
                data_array = [];
                let i = 0;

                await data.map(async (item) => {



                    let game_not_name = item.game_name;
                    let win_number_not = open_number.toString().split("").reduce((acc, curr) => {
                        return acc + Number(curr)
                    }, 0)
                    if (win_number_not > 9)
                        win_number_not = win_number_not % 10;
                    let win_amt = 0;
                    let points = 0;

                    if (item.pana == 'Single Digit') {
                        win_number = open_number.toString().split("").reduce((acc, curr) => {
                            return acc + Number(curr)
                        }, 0)
                        if (win_number > 9)
                            win_number = win_number % 10;

                        if (win_number == item.digits) {
                            win_amt = (single_digit_val_2 / single_digit_val_1) * item.points;

                            points = item.points;

                            data_array[i]['points'] = item.points;
                            data_array[i]['user_id'] = item.user_id;
                            data_array[i]['user_name'] = item.user_name;
                            data_array[i]['pana'] = item.pana;
                            data_array[i]['bid_tx_id'] = item.bid_tx_id;
                            data_array[i]['win_amt'] = win_amt;

                        }
                    }
                    else if (item.pana == 'Triple Pana') {
                        if (open_number == item.digits) {
                            win_amt = (tripple_pana_val_2 / tripple_pana_val_1) * item.points;

                            points = item.points;

                            data_array[i]['points'] = item.points;
                            data_array[i]['user_id'] = item.user_id;
                            data_array[i]['user_name'] = item.user_name;
                            data_array[i]['pana'] = item.pana;
                            data_array[i]['bid_tx_id'] = item.bid_tx_id;
                            data_array[i]['win_amt'] = win_amt;
                        }
                    }
                    else if (item.pana == 'Double Pana') {
                        if (open_number == item.digits) {
                            win_amt = (double_pana_val_2 / double_pana_val_1) * item.points;

                            points = item.points;

                            data_array[i]['points'] = item.points;
                            data_array[i]['user_id'] = item.user_id;
                            data_array[i]['user_name'] = item.user_name;
                            data_array[i]['pana'] = item.pana;
                            data_array[i]['bid_tx_id'] = item.bid_tx_id;
                            data_array[i]['win_amt'] = win_amt;
                        }
                    }

                    else if (item.pana == 'Single Pana') {
                        if (open_number == item.digits) {
                            win_amt = (single_pana_val_2 / single_pana_val_1) * item.points;

                            points = item.points;

                            data_array[i]['user_id'] = item.user_id;
                            data_array[i]['points'] = item.points;
                            data_array[i]['user_name'] = item.user_name;
                            data_array[i]['pana'] = item.pana;
                            data_array[i]['bid_tx_id'] = item.bid_tx_id;
                            data_array[i]['win_amt'] = win_amt;
                        }
                    }
                    win_amt_sum = win_amt + win_amt_sum;
                    points_amt_sum = points + points_amt_sum;
                    if (win_amt > 0)
                        i++;


                })
            })




        })

        return res.status(200).json({ status: "success", data: data_array, winAmount: win_amt_sum, points: points_amt_sum })

    } catch (error) {
        console.log("error in getOpenWinnerList_starline", error);
        return res.status(500).json({ status: "error", msg: error.message })
    }



};

const usersQueryListGridData = (req, res) => {
    // ToDO
};

const tipsListGridData = (req, res) => {
    // ToDO
};
const addTips = (req, res) => {
    // ToDO
};

const userSendNotification = async (req, res) => {

    try {

        const { user_id, notice_title_english, notice_title_hindi, notification_content_english, notification_content_hindi } = req.body
        const token = req.cookies?.unique_jwt_token
        const user = jwt.verify(token, process?.env?.JWT_SECRET)
        let result
        if (user_id == "all") {
            await user_module.updateMany({}, {

                $set: {
                    notification_status: 1
                }
            })
            result = await user_module.find({}).select("mobile")
        } else {
            result = await user_module.findOneAndUpdate({ _id: user_id }, {
                $set: {
                    notification_status: 1
                }
            }, { new: true })
        }

        if (result.length > 0) {
            await Promise.all(result.map(async (item) => {
                let number = item.mobile


                notice_module.create({
                    phone: String(number),
                    notice_title: notice_title_english,
                    notice_title_hindi: notice_title_hindi,
                    notice_msg: notification_content_english,
                    notice_msg_hindi: notification_content_hindi,
                    status: 1,
                    notice_date: `${new Date().getFullYear()}-${new Date().getMonth()}-${new Date().getDate()}`,
                    insert_date: `${new Date().getFullYear()}-${new Date().getMonth()}-${new Date().getDate()} ${new Date().toLocaleTimeString('en-GB')}`
                })
            }))


            return res.status(200).json({ success: true, msg: "Notification sent successfully" })


        } else {
            return res.status(400).json({ success: false, msg: "User not found" })
        }

    } catch (error) {
        console.log("error in userSendNotification", error);
        return res.status(500).json({ success: false, msg: "Internal Server Error" })
    }

};

// const getAllWalletTransactionHistory = async(req, res) => {
//     try{
//     const {
//     length = 10,
//     start =1,
//     index = 0,
//     order =-1,
//     searchValue,
//     selected_date ,
//     type,
//     } = req.body;


//         const resp = await wallet_trans_history_module.find({},{amount:1, amount_status:1, insert_date:1, transaction_note:1, _id:0 }).populate('userDB_id', 'user_name mobile').lean();
//             if(!resp){
//                 return res.status(404).json({success:false, msg:"No data found"})
//             }


//             // console.log("data from getAllWalletTransactionHistory- ", resp)
//             return res.status(200).json({success:true, msg:"Transaction history fetched successfully", data:resp})
//     }
//     catch(err){
//         console.log("error in getAllWalletTransactionHistory", err);
//         res.status(500).json({success:false, msg:err?.message || "Internal Server Error"})  
//     }


// };

const getAllWalletTransactionHistory = async (req, res) => {
    try {
        const {
            length = 10,
            start = 1,
            index = 0,
            order = -1,
            searchValue = "",
            // todayDate,
            selected_date,
            type,
        } = req.body;

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) * limit : 0;
        const orderDir = parseInt(order);

        const fields = [
            "",
            "user_name",           // 0
            "mobile",              // 1
            "amount",              // 3
            "amount_status",       // 4
            "",                    // 5
            "before_wallet",       // 6
            "after_wallet",         //7 
            "insert_date",         // 8
        ];

        const orderField = fields[index] || "insert_date";
        const searchTerm = searchValue.trim();

        // Build match filter
        const matchFilter = {};

        if (type && type !== "All") {

            matchFilter.amount_status = type == "Debit" ? { $in: [2, 3, 5] } : { $in: [1, 4, 6, 7, 8, 19] };
        }

        if (selected_date) {
            const sd = moment_timeZone.tz(selected_date.trim(), ["DD-MM-YYYY", "YYYY-MM-DD"], "Asia/Kolkata")
            console.log("sd:", sd);
            const startDate = sd.clone().startOf("day").toDate();
            // const td = moment_timeZone.tz(todayDate.trim(), ["DD-MM-YYYY", "YYYY-MM-DD"], "Asia/Kolkata").toDate();
            // const nextDate = moment(date).add(1, 'days');
            console.log("startDate-", startDate)

            matchFilter.insert_date = {
                $lte: startDate,
                // $lt: nextDate.toDate()
            };
        }

        const basePipeline = [
            { $match: matchFilter },
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    amount: 1,
                    amount_status: 1,
                    insert_date: 1,
                    before_wallet: 1,
                    transaction_note: 1,
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile",
                }
            }
        ];

        // Search filtering
        if (searchTerm) {
            const regex = new RegExp(searchTerm, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { mobile: { $regex: regex } },
                        { transaction_note: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$mobile" },
                                    regex
                                }
                            }
                        }
                    ]
                }
            });
        }

        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        // Run parallel queries: results + count
        const [results, totalCountArr] = await Promise.all([
            wallet_trans_history_module.aggregate(pipelineWithPagination),
            wallet_trans_history_module.aggregate([...basePipeline, { $count: "total" }])
        ]);
        // console.log("pipelineWithPagination:", pipelineWithPagination);
        console.log("results:", results);

        const totalFiltered = totalCountArr[0]?.total || 0;

        return res.status(200).json({
            success: true,
            msg: "Transaction history fetched successfully",
            data: results,
            recordsFiltered: totalFiltered,
            limit
        });

    } catch (err) {
        console.error("Error in getAllWalletTransactionHistory:", err);
        res.status(500).json({
            success: false,
            msg: err?.message || "Internal Server Error"
        });
    }
};


const quesListGridData = (req, res) => {
    // not available
};

const getUserData = (req, res) => {
    // not available
};
const getUserSearch = (req, res) => {
    // not available
};

const submitRouletteGame = (req, res) => {
    // not available
};
const rouletteGameNameListGridData = (req, res) => {
    // not available
};

const getRouletteBidHistoryData = (req, res) => {
    // not available
};
const exportOptionRouletteBidHistoryData = (req, res) => {
    // not available
};

const rouletteResultHistoryListGridData = (req, res) => {
    // not available
};

const getRouletteWinningReport = async (req, res) => {
    const date = req.bid_revert_date
    const gamename = req.gamename

    const endDate = new Date(date)

    try {


        const result = await roulette_bid_history_module.aggregate([{
            $match: {
                result_date: {
                    $eq: endDate
                }
            }
        },
        {
            $lookup: {
                from: 'wallet_trans_histories',
                localField: 'result_token',
                foreignField: 'open_result_token',
                as: 'wallet'
            }
        },
        { $unwind: '$wallet' },
        {
            $lookup: {
                from: 'roulette_bid_histories',
                localField: 'wallet.bid_tx_id',
                foreignField: 'bid_tx_id',
                as: 'bid'
            }
        },
        { $unwind: '$bid' },
        {
            $match: {
                'bid.gameDB_id': new mongoose.Types.ObjectId(gamename)
            }
        },
        {
            $lookup: {
                from: 'users',
                localField: 'bid.userDB_id',
                foreignField: '_id',
                as: 'user'
            }
        },
        { $unwind: '$user' },
        {
            $group: {
                _id: '$wallet.tx_request_number',
                user_name: { $first: '$user.user_name' },
                user_id: { $first: '$user._id' },
                game_name: { $first: '$bid.game_name' },
                amount: { $first: '$wallet.amount' },
                transaction_note: { $first: '$wallet.transaction_note' },
                tx_request_number: { $first: '$wallet.tx_request_number' },
                insert_date: { $first: '$wallet.insert_date' },
                digits: { $first: '$bid.digits' },
                points: { $first: '$bid.points' },
                bid_id: { $first: '$bid._id' },
                bid_tx_id: { $first: '$bid.bid_tx_id' }
            }
        },
        {
            $sort: { insert_date: -1 }
        }])

        res.status(200).json({ success: true, data: result })
    } catch (error) {
        console.log("error in getRouletteWinningReport", error);
        res.status(500).json({ success: false, msg: "Internal Server Error" })
    }

};


const cuttingGroupData = async (req, res) => {
    try {
        // console.log("api calledcutting group data");
        const {
            date = "",
            game = "",
            gameType = "",
            session = "",
        } = req.body

        if (!date || !game || !gameType || !session) {
            return res.status(400).json({ success: false, msg: "All fields are required" })
        }

        // const singleD_bid_amount = await bid_history_module.aggregate([
        //     {$match : {pay_status:{$ne:1}}} ,
        //     {
        //         $group:{
        //             _id: null,
        //             total : {$sum : '$points'}
        //         }
        //     }
        // ])




        // return res.status(200).json({ success: true, msg: "api calledcutting group data" })
    } catch (err) {
        console.log("error in cuttingGroupData", err);
        return res.status(500).json({ success: false, msg: "Internal Server Error" })
    }
}




const addManualPaymentDetails = async (req, res) => {
    try {
        console.log("API called inside addManualPaymentDetails");

        // Check if file was uploaded
        if (!req.file) {
            return res.status(400).json({
                success: false,
                message: "QR code image is required"
            });
        }

        // Extract data from request
        const { upiId, bankDetails } = req.body;

        // Create new payment detail
        const newPaymentDetail = new ManualPayment({
            qrCode: {
                data: req.file.buffer,
                contentType: req.file.mimetype
            },
            upiId: upiId || "",
            bankDetails: bankDetails || ""
        });

        // Save to database
        await newPaymentDetail.save();

        res.status(201).json({
            success: true,
            message: "Payment details added successfully",
            data: newPaymentDetail
        });

    } catch (err) {
        console.log("Error in addManualPaymentDetails:", err);
        res.status(500).json({
            success: false,
            message: "Internal server error"
        });
    }
}


// const getAllUsersBankDetails = async(req,res)=>{
//     try {
//         const accNumber = req?.body || null;
//         console.log(accNumber.searchValue)

//         if (!accNumber) {
//             return res.status(401).json({ success: false, msg: 'User not found' });
//         }

//         // let bankDetails = await user_bank_details_module.find({ userDB_id: userData._id }).lean();
//         let bankDetailsArr = await user_bank_details_module.find({ac_number : accNumber}).lean();
//         if (bankDetailsArr.length == 0) {
//             return res.status(404).json({
//                 success: false,
//                 msg: "No bank details found"
//             });
//         }
//         console.log("All Users Bank Details", bankDetailsArr)
//         let bankDetails = bankDetailsArr;

//         return res.json({
//             success: true,
//             bank_details: bankDetails,
//             msg: 'All Users Bank Details',
//         });

//     } catch (error) {
//         console.error('Error in apiUserBankDetails:', error);
//         return res.status(500).json({ success: false, msg: 'Internal Server ErrorIIII' });
//     }
// }

// Manual payment routes


const getAllUsersBankDetails = async (req, res) => {
    try {
        const { searchValue } = req.body; // Destructure to get searchValue directly

        console.log('Search Value:', searchValue);

        if (!searchValue) {
            return res.status(400).json({ success: false, msg: 'Account number is required' });
        }

        // Convert searchValue to number since ac_number is defined as Number
        const accountNumber = parseInt(searchValue);

        if (isNaN(accountNumber)) {
            return res.status(400).json({ success: false, msg: 'Invalid account number format' });
        }

        let bankDetailsArr = await user_bank_details_module.find({ ac_number: accountNumber }).populate('userDB_id').lean();

        if (bankDetailsArr.length == 0) {
            return res.status(404).json({
                success: false,
                msg: "No bank details found"
            });
        }

        console.log("All Users Bank Details", bankDetailsArr);

        return res.json({
            success: true,
            bank_details: bankDetailsArr,
            msg: 'Users Bank Details Found',
        });

    } catch (error) {
        console.error('Error in apiUserBankDetails:', error);
        return res.status(500).json({ success: false, msg: 'Internal Server Error' });
    }
}



const getManualPaymentDetails = async (req, res) => {
    try {
        const paymentDetails = await ManualPayment.find().sort({ createdAt: -1 });

        // Convert buffer to base64 for frontend
        const detailsWithBase64 = paymentDetails.map(detail => {
            const obj = detail.toObject();
            if (obj.qrCode && obj.qrCode.data) {
                obj.qrCodeData = `data:${obj.qrCode.contentType};base64,${obj.qrCode.data.toString('base64')}`;
            }
            return obj;
        });

        let finalData = {};

        if (detailsWithBase64[0]._id) {
            finalData._id = detailsWithBase64[0]._id
        }
        if (detailsWithBase64[0].qrCodeData) {
            finalData.qrCodeData = detailsWithBase64[0].qrCodeData
        }

        res.status(200).json({
            success: true,
            message: "QR code image fetched successfully",
            data: finalData,
        });
    } catch (err) {
        console.log("Error in getManualPaymentDetails:", err);
        res.status(500).json({
            success: false,
            message: "Internal server error"
        });
    }
}

const deleteManualPaymentDetails = async (req, res) => {
    try {
        const data = req?.body?.data;

        console.log(`(((((((()))))) ~ adminController.js:14767 ~ deleteManualPaymentDetails ~ id:`, req.body);

        if (!data?.id) {
            return res.status(400).json({
                success: false,
                message: "Payment detail id is required"
            });
        }

        const deletedDetail = await ManualPayment.findByIdAndDelete(data?.id);

        // console.log(`(((((((()))))) ~ adminController.js:14771 ~ deleteManualPaymentDetails ~ deletedDetail:`, deletedDetail);

        if (!deletedDetail) {
            return res.status(404).json({
                success: false,
                message: "Payment detail not found"
            });
        }

        res.status(200).json({
            success: true,
            message: "Payment detail deleted successfully"
        });
    } catch (err) {
        console.log("Error in deleteManualPaymentDetails:", err);
        res.status(500).json({
            success: false,
            message: "Internal server error"
        });
    }
}

// Create App Update
const createAppUpdate = async (req, res) => {
    try {
        const { version, change_logs, content, status = 0 } = req.body;
        const adminId = req.admin._id;

        // Check if version already exists
        const existingUpdate = await app_link_module.findOne({ version });
        if (existingUpdate) {
            return res.status(400).json({
                success: false,
                msg: 'This version already exists'
            });
        }

        if (!req.file) {
            return res.status(400).json({
                success: false,
                msg: 'APK file is required'
            });
        }

        // Create uploads directory if it doesn't exist
        const uploadsDir = path.join(__dirname, '../uploads/app-updates');
        if (!fs.existsSync(uploadsDir)) {
            fs.mkdirSync(uploadsDir, { recursive: true });
        }

        // Generate app link (download URL)
        const app_link = `/downloads/app-updates/${req.file.filename}`;

        console.log(`(((((((()))))) ~ adminController.js:14853 ~ createAppUpdate ~ app_link:`, app_link);

        const newUpdate = new app_link_module({

            app_link,
            change_logs,
            content,
            version,
            status: status || 0
        });

        await newUpdate.save();
        console.log(`(((((((()))))) ~ adminController.js:14855 ~ createAppUpdate ~ newUpdate:`, newUpdate);

        res.status(201).json({
            success: true,
            msg: 'App update created successfully',
            data: newUpdate
        });

    } catch (error) {
        console.error('Error creating app update:', error);
        res.status(500).json({
            success: false,
            msg: 'Server error occurred while creating app update'
        });
    }
};

// Get All App Updates
const getAppUpdates = async (req, res) => {
    try {
        const updates = await app_link_module.find().sort({ version: -1, createdAt: -1 });

        res.json({
            success: true,
            data: updates
        });

    } catch (error) {
        console.error('Error fetching app updates:', error);
        res.status(500).json({
            success: false,
            msg: 'Server error occurred while fetching app updates'
        });
    }
};

// Toggle App Update Status
const toggleAppUpdateStatus = async (req, res) => {
    try {
        const { updateId, status } = req.body;

        if (![0, 1].includes(parseInt(status))) {
            return res.status(400).json({
                success: false,
                msg: 'Invalid status value. Use 0 (inactive) or 1 (active)'
            });
        }

        const update = await app_link_module.findByIdAndUpdate(
            updateId,
            {
                status: parseInt(status),
                updatedAt: new Date()
            },
            { new: true }
        );

        if (!update) {
            return res.status(404).json({
                success: false,
                msg: 'App update not found'
            });
        }

        res.json({
            success: true,
            msg: 'Status updated successfully',
            data: update
        });

    } catch (error) {
        console.error('Error toggling app update status:', error);
        res.status(500).json({
            success: false,
            msg: 'Server error occurred while updating status'
        });
    }
};

// Delete App Update
const deleteAppUpdate = async (req, res) => {
    try {
        const { updateId } = req.body;

        const update = await app_link_module.findById(updateId);
        if (!update) {
            return res.status(404).json({
                success: false,
                msg: 'App update not found'
            });
        }

        // Delete the APK file from server
        if (update.app_link) {
            const filename = update.app_link.split('/').pop();
            const filePath = path.join(__dirname, '../uploads/app-updates', filename);

            if (fs.existsSync(filePath)) {
                fs.unlinkSync(filePath);
            }
        }

        await app_link_module.findByIdAndDelete(updateId);

        res.json({
            success: true,
            msg: 'App update deleted successfully'
        });

    } catch (error) {
        console.error('Error deleting app update:', error);
        res.status(500).json({
            success: false,
            msg: 'Server error occurred while deleting app update'
        });
    }
};

// Get Latest Active App Update
const getLatestAppUpdate = async (req, res) => {
    try {
        const latestUpdate = await app_link_module.findOne({ status: 1 })
            .sort({ version: -1, createdAt: -1 });

        if (!latestUpdate) {
            return res.status(404).json({
                success: false,
                msg: 'No active app version found'
            });
        }

        res.json({
            success: true,
            data: latestUpdate
        });

    } catch (error) {
        console.error('Error fetching latest app update:', error);
        res.status(500).json({
            success: false,
            msg: 'Server error occurred while fetching latest app update'
        });
    }
};


// get user total add fund and withdraw fund report

// In your backend routes file (e.g., routes/admin.js)
// const userTotalAddFundAndWithdrawFundAmount = async (userDB_id) => {
//     try {
//         // const { userDB_id, accessing } = req.body; // Assuming you have authentication middleware

//         // Verify admin permissions if needed
//         // if (!accessing || !hasPermission(accessing, '7.1')) {
//         //     return res.status(403).json({ success: false, msg: 'Access denied' });
//         // }

//         // Aggregate wallet transactions to calculate totals
//         const result = await wallet_trans_history_module.aggregate([
//             {
//                 $match: {
//                     userDB_id: new mongoose.Types.ObjectId(userDB_id)
//                 }
//             },
//             {
//                 $group: {
//                     _id: null,
//                     totalDeposit: {
//                         $sum: {
//                             $cond: {
//                                 if: { $in: ["$amount_status", [1, 4, 6, 7, 8, 19]] },
//                                 then: "$amount",
//                                 else: 0
//                             }
//                         }
//                     },
//                     totalWithdrawal: {
//                         $sum: {
//                             $cond: {
//                                 if: { $in: ["$amount_status", [2, 3, 5]] },
//                                 then: "$amount",
//                                 else: 0
//                             }
//                         }
//                     }
//                 }
//             }
//         ]);

//         // If no transactions found, return zeros
//         const summary = result.length > 0
//             ? result[0]
//             : { totalDeposit: 0, totalWithdrawal: 0 };

//         res.json({
//             success: true,
//             totalDeposit: summary.totalDeposit,
//             totalWithdrawal: summary.totalWithdrawal,
//             netBalance: summary.totalDeposit - summary.totalWithdrawal
//         });
//     } catch (error) {
//         console.error('Error fetching transaction summary:', error);
//         res.status(500).json({
//             success: false,
//             msg: 'Server error while fetching transaction summary'
//         });
//     }
// };

const userTotalAddFundAndWithdrawFundAmount = async (userDB_id) => {
    try {
        // Aggregate wallet transactions to calculate totals
        const result = await wallet_trans_history_module.aggregate([
            {
                $match: {
                    userDB_id: new mongoose.Types.ObjectId(userDB_id)
                }
            },
            {
                $group: {
                    _id: null,
                    totalDeposit: {
                        $sum: {
                            $cond: {
                                if: { $in: ["$amount_status", [1, 4, 6, 7, 8, 19]] },
                                then: "$amount",
                                else: 0
                            }
                        }
                    },
                    totalWithdrawal: {
                        $sum: {
                            $cond: {
                                if: { $in: ["$amount_status", [2, 3, 5]] },
                                then: "$amount",
                                else: 0
                            }
                        }
                    }
                }
            }
        ]);

        // If no transactions found, return zeros
        const summary = result.length > 0
            ? result[0]
            : { totalDeposit: 0, totalWithdrawal: 0 };

        // Return the data instead of sending response
        return {
            success: true,
            totalDeposit: summary.totalDeposit,
            totalWithdrawal: summary.totalWithdrawal,
            netBalance: summary.totalDeposit - summary.totalWithdrawal
        };
    } catch (error) {
        console.error('Error fetching transaction summary:', error);
        // Return error instead of sending response
        return {
            success: false,
            msg: 'Server error while fetching transaction summary'
        };
    }
};


// const fetchOpenCloseGameResultHistory = async (req, res) => {

//     try {

//         const { gameDb_id, bid_date, openDigit, closeDigit } = req?.body;

//         console.log("req?.body ", req?.body)

//         if (!gameDb_id || !bid_date || (!openDigit && !closeDigit)) {
//             return res.status(404).json({ success: false, msg: "gameId, bid_Date and session Digit not found !" })
//         }


//         let filter = { pay_status: 1 };

//         if (openDigit) {
//             console.log("found open digit")
//             filter.digits = openDigit;
//             filter.session = "Open";
//         }
//         if (closeDigit) {
//             console.log("found close digit")
//             filter.digits = closeDigit;
//             filter.session = "Close";
//         }

//         if (bid_date) {
//             filter.bid_date = new Date(bid_date);;
//         }



//         console.log("chekc filter ", filter)


//         let withdrawRequestData = await bid_history_module.aggregate([
//             {
//                 $match: filter
//             },
//         ]);
//         // {
//         //     $lookup: {
//         //         from: 'users',
//         //         localField: 'userDB_id',
//         //         foreignField: '_id',
//         //         as: 'userData'
//         //     }
//         // },
//         // {
//         //     $lookup: {
//         //         from: 'wallet_trans_histories',
//         //         localField: 'gameDB_id',
//         //         foreignField: '_id',
//         //         as: 'gameData'
//         //     }
//         // },
//         // { $unwind: { path: '$userData', preserveNullAndEmptyArrays: true } },
//         // { $unwind: { path: '$gameData', preserveNullAndEmptyArrays: true } },
//         // {
//         //     $project: {
//         //         fund_payment_receipt: 1,
//         //         fund_status: 1,
//         //         remark: 1,
//         //         payment_method: 1,
//         //         tx_request_number: 1,
//         //         amount: 1,
//         //         withdraw_type: 1,
//         //         insert_date: 1,
//         //         paytm_number: 1,
//         //         ac_holder_name: 1,
//         //         ac_number: 1,
//         //         google_pay_number: 1,
//         //         phone_pay_number: 1,
//         //         bank_name: 1,
//         //         branch_address: 1,
//         //         ifsc_code: 1,
//         //         user_name: '$userData.user_name',
//         //         accepte_date: '$tx_info.insert_date',
//         //         withdraw_requestDB_id: 1,
//         //         userDB_id: 1,
//         //     }
//         // }

//         console.log("check the final data before the resp.", withdrawRequestData)

//         return res.status(200).json({ success: true, msg: "data fetched successfully", data: withdrawRequestData })


//     } catch (err) {

//         console.log(err)

//     }

// }

const fetchOpenCloseGameResultHistory = async (req, res) => {
    try {
        const { gameDb_id, bid_date, openDigit, closeDigit } = req?.body;

        console.log("req?.body ", req?.body);

        if (!gameDb_id || !bid_date || (!openDigit && !closeDigit)) {
            return res.status(404).json({ success: false, msg: "gameId, bid_Date and session Digit not found !" });
        }

        let filter = {
            pay_status: 1,
            gameDB_id: new ObjectId(gameDb_id) // Now ObjectId is defined
        };

        // Handle session and digit filtering
        if (openDigit) {
            console.log("found open digit");
            filter.digits = openDigit;
            filter.session = "Open";
        }
        if (closeDigit) {
            console.log("found close digit");
            filter.digits = closeDigit;
            filter.session = "Close";
        }

        // Handle date range filtering for full day
        // if (bid_date) {
        //     const startDate = new Date(bid_date);
        //     // console.log("ðŸš€ ~ fetchOpenCloseGameResultHistory ~ startDate:", startDate)
        //     const endDate = new Date(startDate);
        //     endDate.setDate(endDate.getDate() + 1);
        //     endDate.setMilliseconds(endDate.getMilliseconds() - 1);

        //     // console.log("ðŸš€ ~ fetchOpenCloseGameResultHistory ~ endDate:", endDate)

        //     console.log("Date range:", {
        //         start: startDate,
        //         end: endDate,
        //         startISO: startDate.toISOString(),
        //         endISO: endDate.toISOString()
        //     });

        //     filter.bid_date = {
        //         $gte: startDate,
        //         $lt: endDate
        //     };
        // }

        if (bid_date) {
            const startDate = moment_timeZone.tz(bid_date, "Asia/Kolkata").startOf('day');
            const endDate = startDate.clone().endOf('day');

            // console.log("ðŸš€ ~ fetchOpenCloseGameResultHistory ~ startDate:", startDate.toDate());
            // console.log("ðŸš€ ~ fetchOpenCloseGameResultHistory ~ endDate:", endDate.toDate());

            console.log("Date range:", {
                start: startDate.toDate(),
                end: endDate.toDate(),
                startISO: startDate.toISOString(),
                endISO: endDate.toISOString()
            });

            filter.bid_date = {
                $gte: startDate.toDate(),
                $lt: endDate.toDate()
            };
        }

        console.log("Final filter:", JSON.stringify(filter, null, 2));

        let withdrawRequestData = await bid_history_module.aggregate([
            {
                $match: filter
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            {
                $unwind: {
                    path: '$userData',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $project: {
                    _id: 1,
                    userDB_id: 1,
                    gameDB_id: 1,
                    game_name: 1,
                    pana: 1,
                    session: 1,
                    digits: 1,
                    winning_points: 1,
                    closedigits: 1,
                    points: 1,
                    bid_tx_id: 1,
                    status: 1,
                    pay_status: 1,
                    bid_date: 1,
                    insert_date: 1,
                    open_result_token: 1,
                    // User data
                    "userData._id": 1,
                    "userData.user_name": 1,
                    "userData.mobile": 1,
                    "userData.profile_pic": 1,
                    "userData.wallet_balance": 1
                }
            },
            {
                $sort: { bid_date: -1 }
            }
        ]);

        // console.log("Records found:", withdrawRequestData.length);
        // if (withdrawRequestData.length > 0) {
        //     console.log("Sample record:", withdrawRequestData[0]);
        // }

        return res.status(200).json({
            success: true,
            msg: "data fetched successfully",
            data: withdrawRequestData
        });

    } catch (err) {
        console.error("Error in fetchOpenCloseGameResultHistory:", err);
        return res.status(500).json({
            success: false,
            msg: "Internal server error"
        });
    }
};


// const fetchOpenCloseGameResultHistory = async (req, res) => {
//     try {
//         const { gameDb_id, bid_date, openDigit, closeDigit } = req?.body;

//         console.log("req?.body ", req?.body);

//         if (!gameDb_id || !bid_date || (!openDigit && !closeDigit)) {
//             return res.status(404).json({ success: false, msg: "gameId, bid_Date and session Digit not found !" });
//         }
//         let filter = { 
//             pay_status: 1,
//             gameDB_id: gameDb_id
//         };

//         // Handle session and digit filtering
//         if (openDigit) {
//             console.log("found open digit");
//             filter.digits = openDigit;
//             filter.session = "Open";
//         }
//         if (closeDigit) {
//             console.log("found close digit");
//             filter.digits = closeDigit;
//             filter.session = "Close";
//         }

//         // Handle date range filtering for full day
//         if (bid_date) {
//             const startDate = new Date(bid_date);
//             const endDate = new Date(startDate);
//             endDate.setDate(endDate.getDate() + 1); // Next day
//             endDate.setMilliseconds(endDate.getMilliseconds() - 1); // End of day (23:59:59.999)

//             console.log("Date range:", {
//                 start: startDate,
//                 end: endDate,
//                 startISO: startDate.toISOString(),
//                 endISO: endDate.toISOString()
//             });

//             filter.bid_date = {
//                 $gte: startDate,
//                 $lt: endDate
//             };
//         }

//         console.log("Final filter:", JSON.stringify(filter, null, 2));

//         let withdrawRequestData = await bid_history_module.aggregate([
//             {
//                 $match: filter
//             },
//             {
//                 $lookup: {
//                     from: 'users',
//                     localField: 'userDB_id',
//                     foreignField: '_id',
//                     as: 'userData'
//                 }
//             },
//             { 
//                 $unwind: { 
//                     path: '$userData', 
//                     preserveNullAndEmptyArrays: true 
//                 } 
//             },
//             {
//                 $project: {
//                     _id: 1,
//                     userDB_id: 1,
//                     gameDB_id: 1,
//                     game_name: 1,
//                     pana: 1,
//                     session: 1,
//                     digits: 1,
//                     winning_points: 1,
//                     closedigits: 1,
//                     points: 1,
//                     bid_tx_id: 1,
//                     status: 1,
//                     pay_status: 1,
//                     bid_date: 1,
//                     insert_date: 1,
//                     open_result_token: 1,
//                     // User data
//                     "userData._id": 1,
//                     "userData.user_name": 1,
//                     "userData.mobile": 1,
//                     "userData.profile_pic": 1,
//                     "userData.wallet_balance": 1
//                 }
//             },
//             {
//                 $sort: { bid_date: -1 } // Optional: sort by bid date
//             }
//         ]);

//         console.log("Records found:", withdrawRequestData.length);
//         console.log("Sample record:", withdrawRequestData[0]);

//         return res.status(200).json({ 
//             success: true, 
//             msg: "data fetched successfully", 
//             data: withdrawRequestData 
//         });

//     } catch (err) {
//         console.error("Error in fetchOpenCloseGameResultHistory:", err);
//         return res.status(500).json({ 
//             success: false, 
//             msg: "Internal server error" 
//         });
//     }
// };


const OcCuttingData = async (req, res) => {
    try {
        const {
            date,
            game_name,
            session,
            length = 10,
            start = 1,
            searchValue = ""
        } = req.body;

        // Build match conditions
        const matchConditions = {};

        if (date) {
            const startDate = new Date(date);
            const endDate = new Date(date);
            endDate.setHours(23, 59, 59, 999);

            matchConditions.bid_date = {
                $gte: startDate,
                $lte: endDate
            };
        }

        if (game_name && game_name !== 'all' && game_name !== 'Select an option') {
            matchConditions.game_name = game_name;
        }

        if (session && session !== 'all' && session !== 'Select Session') {
            matchConditions.session = session;
        }

        // Calculate pagination
        const limit = parseInt(length);
        const skip = (parseInt(start) - 1) * limit;

        // Main aggregation pipeline
        const pipeline = [
            { $match: matchConditions },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'user'
                }
            },
            { $unwind: '$user' },
            {
                $addFields: {
                    calculated_digit: { $mod: [{ $sum: { $map: { input: { $split: ["$digits", ""] }, as: "digit", in: { $toInt: "$$digit" } } } }, 10] },
                    pana_category: {
                        $switch: {
                            branches: [
                                {
                                    case: { $eq: [{ $strLenCP: "$pana" }, 1] },
                                    then: "Single Digit"
                                },
                                {
                                    case: { $eq: [{ $strLenCP: "$pana" }, 2] },
                                    then: "Jodi Digit"
                                },
                                {
                                    case: {
                                        $and: [
                                            { $eq: [{ $strLenCP: "$pana" }, 3] },
                                            { $eq: [{ $size: { $setUnion: { $map: { input: { $split: ["$pana", ""] }, as: "char", in: "$$char" } } } }, 3] }
                                        ]
                                    },
                                    then: "Single Pana"
                                },
                                {
                                    case: {
                                        $and: [
                                            { $eq: [{ $strLenCP: "$pana" }, 3] },
                                            { $eq: [{ $size: { $setUnion: { $map: { input: { $split: ["$pana", ""] }, as: "char", in: "$$char" } } } }, 2] }
                                        ]
                                    },
                                    then: "Double Pana"
                                },
                                {
                                    case: {
                                        $and: [
                                            { $eq: [{ $strLenCP: "$pana" }, 3] },
                                            { $eq: [{ $size: { $setUnion: { $map: { input: { $split: ["$pana", ""] }, as: "char", in: "$$char" } } } }, 1] }
                                        ]
                                    },
                                    then: "Triple Pana"
                                }
                            ],
                            default: "Unknown"
                        }
                    }
                }
            },
            {
                $group: {
                    _id: {
                        digit: "$calculated_digit",
                        game_name: "$game_name",
                        session: "$session",
                        game_type: "$pana_category",
                        date: { $dateToString: { format: "%Y-%m-%d", date: "$bid_date" } }
                    },
                    total_points: { $sum: "$points" },
                    total_winning_points: { $sum: "$winning_points" },
                    count: { $sum: 1 },
                    pana: { $first: "$pana" },
                    digits: { $first: "$digits" }
                }
            },
            {
                $group: {
                    _id: "$_id.digit",
                    digit_data: {
                        $push: {
                            game_name: "$_id.game_name",
                            session: "$_id.session",
                            game_type: "$_id.game_type",
                            date: "$_id.date",
                            total_points: "$total_points",
                            total_winning_points: "$total_winning_points",
                            count: "$count",
                            pana: "$pana",
                            digits: "$digits"
                        }
                    },
                    digit_total_points: { $sum: "$total_points" }
                }
            },
            { $sort: { "_id": 1 } }
        ];

        // Add search filter if provided
        if (searchValue) {
            pipeline.splice(1, 0, {
                $match: {
                    $or: [
                        { game_name: { $regex: searchValue, $options: 'i' } },
                        { pana: { $regex: searchValue, $options: 'i' } },
                        { digits: { $regex: searchValue, $options: 'i' } },
                        { session: { $regex: searchValue, $options: 'i' } }
                    ]
                }
            });
        }

        // Get total count for pagination
        const countPipeline = [...pipeline, { $count: "total" }];
        const totalCountResult = await bid_history_module.aggregate(countPipeline);
        const totalCount = totalCountResult[0]?.total || 0;

        // Add pagination
        pipeline.push({ $skip: skip }, { $limit: limit });

        // Execute aggregation
        const results = await bid_history_module.aggregate(pipeline);

        // Calculate totals for all digits
        const totalAmountPipeline = [
            { $match: matchConditions },
            {
                $group: {
                    _id: null,
                    total_amount: { $sum: "$points" }
                }
            }
        ];

        const totalAmountResult = await bid_history_module.aggregate(totalAmountPipeline);
        const totalAmount = totalAmountResult[0]?.total_amount || 0;

        // Format the response data
        const formattedData = [];
        let grandTotal = {
            single_digit: 0,
            jodi_digit: 0,
            single_pana: 0,
            double_pana: 0,
            triple_pana: 0,
            sp: 0,
            dp: 0,
            tp: 0,
            half_sangam: 0,
            full_sangam: 0,
            total_amount: 0
        };

        // Process results for each digit (0-9)
        for (let digit = 0; digit <= 9; digit++) {
            const digitData = results.find(r => r._id === digit);

            if (digitData) {
                const digitInfo = {
                    digit: digit,
                    single_digit: 0,
                    jodi_digit: 0,
                    single_pana: 0,
                    double_pana: 0,
                    triple_pana: 0,
                    sp: 0,
                    dp: 0,
                    tp: 0,
                    half_sangam: 0,
                    full_sangam: 0,
                    game: digitData.digit_data[0]?.game_name || '',
                    session: digitData.digit_data[0]?.session || '',
                    game_type: 'Single',
                    date: digitData.digit_data[0]?.date || '',
                    amount: digitData.digit_total_points
                };

                // Categorize the data
                digitData.digit_data.forEach(item => {
                    switch (item.game_type) {
                        case 'Single Digit':
                            digitInfo.single_digit = item.total_points;
                            grandTotal.single_digit += item.total_points;
                            break;
                        case 'Jodi Digit':
                            digitInfo.jodi_digit = item.total_points;
                            grandTotal.jodi_digit += item.total_points;
                            break;
                        case 'Single Pana':
                            digitInfo.single_pana = item.total_points;
                            grandTotal.single_pana += item.total_points;
                            break;
                        case 'Double Pana':
                            digitInfo.double_pana = item.total_points;
                            grandTotal.double_pana += item.total_points;
                            break;
                        case 'Triple Pana':
                            digitInfo.triple_pana = item.total_points;
                            grandTotal.triple_pana += item.total_points;
                            break;
                    }
                });

                formattedData.push(digitInfo);
            } else {
                // Add empty row for digits with no data
                formattedData.push({
                    digit: digit,
                    single_digit: 0,
                    jodi_digit: 0,
                    single_pana: 0,
                    double_pana: 0,
                    triple_pana: 0,
                    sp: 0,
                    dp: 0,
                    tp: 0,
                    half_sangam: 0,
                    full_sangam: 0,
                    game: '',
                    session: '',
                    game_type: 'Single',
                    date: '',
                    amount: 0
                });
            }
        }

        // Add total row
        const totalRow = {
            digit: 'Total',
            single_digit: grandTotal.single_digit,
            jodi_digit: grandTotal.jodi_digit,
            single_pana: grandTotal.single_pana,
            double_pana: grandTotal.double_pana,
            triple_pana: grandTotal.triple_pana,
            sp: 0,
            dp: 0,
            tp: 0,
            half_sangam: 0,
            full_sangam: 0,
            game: '',
            session: '',
            game_type: '',
            date: '',
            amount: totalAmount
        };

        formattedData.unshift(totalRow);

        res.json({
            success: true,
            data: formattedData,
            total: totalCount,
            total_amount: totalAmount,
            applied_filters: {
                date: date || '-',
                market: game_name || '-',
                session: session || '-'
            }
        });

    } catch (error) {
        console.error('Error in OcCuttingData:', error);
        res.status(500).json({
            success: false,
            message: 'Server error',
            error: error.message
        });
    }
};


module.exports = {
    addManualPaymentDetails,
    getManualPaymentDetails,
    deleteManualPaymentDetails,
    subAdminListGridData,
    unApprovedUserListGridData,
    getMarketBidDetails,
    getSearchMarketBidDetails,
    autoFundRequestListGridData,
    acceptAutoFundRequest,
    rejectAutoFundRequest,
    deleteAutoFundRequest,
    getDashboardWithdrawReportDetails,
    loginCheck,
    forgotPassword,
    updatePassword,
    blockDataFunction,
    marketOpenCloseFunction,
    userListGridData,
    userUpdateWallet,
    acceptFundRequest,
    rejectFundRequest,
    getMiniGamesList,
    creditTransactionTableGridData,
    debitTransactionTableGridData,
    userBidHistoryTableGridData,
    userWinningHistoryData,
    allowedBetting,
    changeLogoutStatus,
    addSubAdmin,
    addMaster,
    addBalanceUserWallet,
    withdrawBalanceUserWallet,
    changeSecurityPin,
    fundRequestListGridData,
    withdrawRequestListGridData,
    approveWithdrawRequest,
    rejectWithdrawRequest,
    noticeListGridData,
    ideaListGridData,
    addNotice,
    addAdminBankDetail,
    addAdminUpiDetail,
    addAdminUpiUpdateOtpCheck,
    addAppLink,
    addAdminFixValues_with_maintainence,
    addGameRates,
    lotteryNameListGridData,
    addLottery,
    deleteLottery,
    ticketHistoryListGridData,
    lotteryResultListLoadData,
    getLotteryListForResult,
    getDecleareLotteryData,
    saveLotteryData,
    decleareLotteryData,
    getLotteryWinnerList,
    gameNameListGridData,
    addUpdateGame,
    addOffDay,
    deleteGameName,
    getPredictWinnerList,
    checkOpenMarketResultDeclaration,
    starlineGameNameListGridData,
    addUpdateStarlineGame,
    editStarlineGame,
    addStarelineGameRates,
    starlineUserBidHistory,
    getStarlineBidHistoryData,
    exportOptionBidHistoryData,
    getDecleareStarlineGameData,
    saveOpenStarlineGameData,
    decleareOpenStarlineData,
    deleteOpenStarlineResultData,
    getOpenStarlineWinnerList,
    getStarlineSellReport,
    getStarlineWinningReport,
    starlineResultHistoryListGridData,
    starlineResultHistoryListLoadData,
    getStarlineWinnerList,
    galidisswarGameNameListGridData,
    addUpdateGalidisswarGame,
    getGalidisswarBidHistoryData,
    exportOptionGalidisswarBidHistoryData,
    updateGaliDissawarBid,
    getDecleareGalidisswarGameData,
    getOpenData,
    getCloseData,
    saveGalidisswarGameData,
    decleareGalidisswarData,
    getGalidisswarWinnerList,
    deleteOpenGalidisswarResultData,
    getGalidisswarSellReport,
    getGalidisswarWinningReport,
    galidisswarResultHistoryListGridData,
    ideasListGridData,
    deleteIdea,
    galidisswarResultHistoryListLoadData,
    getGalidisswarWinnerList_declare,
    getBidRevertData,
    refundAmount,
    addGamesTime,
    changeGameTime,
    tinymceUploadImage,
    addHowToPlayData,
    // sliderImagesListGridData,  // slider images
    getSliderImages,
    addSliderImage,
    deleteSliderImage,
    qrcodeImagesListGridData,
    addQrcodeImage,
    deleteQrcodeImage,
    getBidHistoryData,
    updateBid,
    mainMarketReport,
    showDigit,
    getWinningHistoryData,
    resultHistoryListGridData,
    resultHistoryListLoadData,
    getDecleareGameData,
    saveOpenData,
    decleareOpenData_Result,
    decleareCloseData,
    saveCloseData,
    openResultNotificationContinously,


    deleteOpenCloseResultData_Result,
    revertBidCompletely,


    editOpenResultData,
    editCloseResultData,
    getOpenWinnerList_starline,
    getOpenWinnerList,
    getCloseWinnerList,
    // deleteCloseResultData,
    addContactSettings,
    getContactSettings,
    usersQueryListGridData,
    tipsListGridData,
    addTips,
    userSendNotification,
    getCustomerSellReport,
    getAllWalletTransactionHistory,
    quesListGridData,
    getUserData,
    getUserSearch,
    submitRouletteGame,
    rouletteGameNameListGridData,
    getRouletteBidHistoryData,
    exportOptionRouletteBidHistoryData,
    rouletteResultHistoryListGridData,
    getRouletteWinningReport,
    getAutoDepositeHistory,
    viewWithdrawRequest,
    getMainSettings,
    getHowToPlayData,
    updateSubAdmin,
    deleteSubAdmin,
    isAlreadyLogin,
    deleteNotice,
    updateNotice,
    getSendNotification_users_date,
    sendNotification,
    gameNameListGridDataUpdate,
    getGameRates,
    getGameList,
    getUserProfile,
    userReferralTableGridData,
    userAddFundReqTableGridData,
    userWithdrawFundReqTableGridData,
    userBitHistoryDataReqTableGridData,
    userWalletTransactionHistoryDataReqTableGridData,
    userWinningHistoryDataReqTableGridData,
    adminLogout,
    updateBid_with_property,
    getTransferReport,
    getWithdrawReportDetails,
    deleteStarlineGameName,
    getStarlineGameRates,
    deleteGalidisswarGameName,
    getGalidisswarGameRates,
    addGalidisswarGameRates,
    getStarlineGameList,
    getGalidisswarGameList,
    getDashboardTopData,
    getBidReportList,
    getBidWinningReportDetails,
    getWinningReportDetails,
    getStarlineBidRevertData,
    getgalidisswarBidRevertData,
    starlineRefundAmount,
    galidisswarRefundAmount,
    changeWingoResult,
    cuttingGroupData,
    OcCuttingData,
    addManualPaymentDetails,
    createAppUpdate,
    getAppUpdates,
    toggleAppUpdateStatus,
    deleteAppUpdate,
    getLatestAppUpdate,
    moveWithdrawToProcessing,
    userTotalAddFundAndWithdrawFundAmount,
    getFixValue,
    reprocessWithdrawRequest,
    getAllUsersBankDetails,
    fetchOpenCloseGameResultHistory,
}