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 axios = require('axios');


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 bid_archive_history_module = require('../model/bid_archive_history_module');
const wallet_trans_history_module = require('../model/wallet_trans_history_module');
const wallet_trans_archive_history_module = require('../model/wallet_trans_archive_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');
const content_rules_module = require('../model/contents_rules_module');


// const PaymentGateway_module = require('../model/payment_gateway_module');
// const PaymentGatewayLog_module = require('../model/payment_gateways_log');

const DollarBazarSettings = require('../model/DollarBazarSettings');
const ProtonPaySettings = require('../model/ProtonPaySettings');





const admin = require("../firebase/index");

// const DollarBazarService = require('../services/paymentGatewayService');
const PaymentGateway_settings = require('../model/payment_gateway_module');
const PaymentGatewayLog = require('../model/payment_gateways_log');
const checkTransactionStatus = require('../services/dollarbazar.service')
const { doPayout } = require("../services/dollarbazar.payout.service");



// const sendGameResultNotification = require('../helper/onesignalHelper');











// 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 { completeMenus } = 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 { getDefaultHighWaterMark } = require('stream');
const { search } = require('../routes/mobileRoute');
const { refundStarlineWinnings } = require('../utils/beditUser');
const payment_gateway_module = require('../model/payment_gateway_module');



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 || {}
        console.log("🚀 ~ isAlreadyLogin ~ admin:", admin)
        console.log("🚀 ~ isAlreadyLogin ~ admin?.accessMenus[0]:", admin?.accessMenus[0])
        return res.json({
            success: true,
            msg: "You already login",
            redirectRoute: completeMenus[admin?.accessMenus[0]] || '/dashboard',
            adminAccess: admin?.accessMenus,
            admin_user_name: req.admin ? req?.admin?.username : '',
            admin_type: req.admin ? req?.admin?.admin_type : '',
        });

    } 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: completeMenus[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);
        // console.log("🚀 ~ blockDataFunction ~ result:", result)
        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 getManualFundRequests = async (req, res) => {
    try {
        const baseUrl = process?.env?.BASE_URL;
        console.log("🚀 ~ getManualFundRequests ~ process:")
        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 from = req.body.from;
        const to = req.body.to;
        const limit = parseInt(req?.body?.length) || 10;
        const start = parseInt(req?.body?.start) || 0;
        const fieldIndex = req?.body?.fieldIndex || 0;
        const orderField = fields[fieldIndex] || "insert_date";

        // FIX: Default to descending order (-1) for newest first
        const orderDir = req?.body?.order !== undefined ? parseInt(req?.body?.order) : -1;

        // Date parsing with validation
        let startDate, endDate;
        if (from?.trim() && to?.trim()) {
            startDate = moment_timeZone.tz(from.trim(), 'Asia/Kolkata').clone().startOf('day').toDate();
            endDate = moment_timeZone.tz(to.trim(), 'Asia/Kolkata').clone().endOf('day').toDate();
        }

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

        // Filter for manual requests only (deposit_type = 0)
        let typeFilter = { deposit_type: 0 };

        // Status filter
        let statusFilter = {};
        if (req?.body?.fund_status !== undefined && req?.body?.fund_status !== null) {
            statusFilter = { fund_status: parseInt(req.body.fund_status) };
        }

        // Date filter (only apply if dates are provided)
        let dateFilter = {};
        if (startDate && endDate) {
            dateFilter.insert_date = { $gte: startDate, $lte: endDate };
        }

        // Search query
        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"
                                }
                            }
                        },
                    ]
                };
            } 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 all filters
        const finalFilter = {
            ...searchQuery,
            ...statusFilter,
            ...dateFilter,
            ...typeFilter
        };

        // 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",
                    mobile: "$userData.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,
                    fund_payment_receipt: 1,
                    isAction: {
                        $cond: [
                            { $ne: ['$fund_status', 0] },
                            0,
                            1
                        ]
                    }
                }
            },
            { $match: finalFilter },
            { $count: "totalData" },
        ]);

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

        // Main Pipeline - FIXED: Default sort by insert_date descending (newest first)
        const pipeline = [
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    _id: 1,
                    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
                        ]
                    }
                }
            },
            { $match: finalFilter },
            // FIX: Always sort by insert_date descending by default, unless another field is specified
            // { $sort: { [orderField]: orderDir } },
            // In the pipeline, replace the sort stage with:
            { $sort: { insert_date: -1, [orderField]: orderDir } },
            { $skip: start },
            { $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}/uploads/fund-request-receipt/${v.fund_payment_receipt}`
                : null
        }));

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

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


// const getManualFundRequests = 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 from = req.body.from;
//         const to = req.body.to;
//         const limit = parseInt(req?.body?.length) || 10;
//         const start = parseInt(req?.body?.start) || 0;
//         const fieldIndex = req?.body?.fieldIndex || 0;
//         const orderField = fields[fieldIndex] || "insert_date";
//         const orderDir = req?.body?.order || -1;

//         const startDate = moment_timeZone.tz(from?.trim(), 'Asia/Kolkata').clone().startOf('day').toDate();
//         const endDate = moment_timeZone.tz(to?.trim(), 'Asia/Kolkata').clone().endOf('day').toDate();

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

//         // Filter for manual requests only (deposit_type = 0)
//         let typeFilter = { deposit_type: 0 };

//         // Status filter
//         let statusFilter = {};
//         if (req?.body?.fund_status !== undefined && req?.body?.fund_status !== null) {
//             statusFilter = { fund_status: parseInt(req.body.fund_status) };
//         }

//         // Date filter
//         let dateFilter = {};
//         if (startDate && endDate) {
//             dateFilter.insert_date = { $gte: startDate, $lte: endDate };
//         }

//         // Search query
//         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"
//                                 }
//                             }
//                         },
//                     ]
//                 };
//             } 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 all filters
//         const finalFilter = {
//             ...searchQuery,
//             ...statusFilter,
//             ...dateFilter,
//             ...typeFilter
//         };

//         // 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",
//                     mobile: "$userData.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,
//                     fund_payment_receipt: 1,
//                     isAction: {
//                         $cond: [
//                             { $ne: ['$fund_status', 0] },
//                             0,
//                             1
//                         ]
//                     }
//                 }
//             },
//             { $match: finalFilter },
//             { $count: "totalData" },
//         ]);

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

//         // Main Pipeline
//         const pipeline = [
//             {
//                 $lookup: {
//                     from: "users",
//                     localField: "userDB_id",
//                     foreignField: "_id",
//                     as: "userData"
//                 }
//             },
//             { $unwind: "$userData" },
//             {
//                 $project: {
//                     _id: 1,
//                     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
//                         ]
//                     }
//                 }
//             },
//             { $match: finalFilter },
//             { $sort: { [orderField]: orderDir } },
//             { $skip: start },
//             { $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}/uploads/fund-request-receipt/${v.fund_payment_receipt}`
//                 : null
//         }));

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

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


const getAutoFundRequests = async (req, res) => {
    try {
        const fields = [
            "user_name",
            "amount",
            "tx_request_number",
            "payment_method",
            "txn_ref",
            "insert_date",
            "fund_status",
        ];

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

        const startDate = moment_timeZone.tz(from?.trim(), 'Asia/Kolkata').clone().startOf('day').toDate();
        const endDate = moment_timeZone.tz(to?.trim(), 'Asia/Kolkata').clone().endOf('day').toDate();

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

        // Filter for automatic requests only (deposit_type = 1)
        let typeFilter = { deposit_type: 1 };

        // Status filter
        let statusFilter = {};
        if (req?.body?.fund_status !== undefined && req?.body?.fund_status !== null) {
            statusFilter = { fund_status: parseInt(req.body.fund_status) };
        }

        // Date filter
        let dateFilter = {};
        if (startDate && endDate) {
            dateFilter.insert_date = { $gte: startDate, $lte: endDate };
        }

        // Search query
        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    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' } },
                    ]
                };
            }
        }

        // Combine all filters
        const finalFilter = {
            ...searchQuery,
            ...statusFilter,
            ...dateFilter,
            ...typeFilter
        };

        // 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",
                    mobile: "$userData.mobile",
                    amount: 1,
                    tx_request_number: 1,
                    payment_method: 1,
                    txn_ref: 1,
                    fund_status: 1,
                    insert_date: 1,
                    deposit_type: 1
                }
            },
            { $match: finalFilter },
            { $count: "totalData" },
        ]);

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

        // Main Pipeline
        const pipeline = [
            {
                $lookup: {
                    from: "users",
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userData"
                }
            },
            { $unwind: "$userData" },
            {
                $project: {
                    _id: 1,
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile",
                    amount: 1,
                    tx_request_number: 1,
                    payment_method: 1,
                    txn_ref: 1,
                    fund_status: 1,
                    insert_date: 1,
                    deposit_type: 1
                }
            },
            { $match: finalFilter },
            // { $sort: { [orderField]: orderDir } },
            // In the pipeline, replace the sort stage with:
            { $sort: { insert_date: -1, [orderField]: orderDir } },
            { $skip: start },
            { $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"
        }));

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

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


// const refreshPGTransactionStatus = async (req, res) => {
//     try {
//         const { transactionId } = req.body;

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

//         // Find the transaction
//         const transaction = await add_funds_module.findById(transactionId);
//         if (!transaction) {
//             return res.status(404).json({ success: false, msg: "Transaction not found" });
//         }

//         // Only allow refresh for DollarBazar PG transactions
//         if (transaction.deposit_type !== 1 || transaction.payment_method !== "DOLLARBAZAR") {
//             return res.status(400).json({ 
//                 success: false, 
//                 msg: "Only auto DollarBazar PG transactions can be refreshed" 
//             });
//         }

//         // Get orderId from transaction
//         const orderId = transaction.tx_request_number;
//         if (!orderId) {
//             return res.status(400).json({ 
//                 success: false, 
//                 msg: "Transaction reference not found" 
//             });
//         }

//         // Step 1: Authenticate with DollarBazar
//         const authResp = await authenticate(transaction.amount, orderId);
//         if (!authResp || !authResp.api_token || !authResp.id_token) {
//             return res.status(500).json({ 
//                 success: false, 
//                 msg: "Authentication failed with payment gateway" 
//             });
//         }

//         // Step 2: Check status with DollarBazar
//         const statusResp = await checkStatus(authResp.api_token, authResp.id_token, orderId);

//         console.log("🔍 Status check response:", statusResp);

//         if (statusResp && statusResp.success) {
//             let newFundStatus = transaction.fund_status;
//             let updateData = {
//                 gateway_response: statusResp,
//                 updated_at: new Date()
//             };

//             // Map DollarBazar status to your fund_status
//             if (statusResp.data) {
//                 const dbData = statusResp.data;

//                 // Check if transaction is successful based on documentation
//                 if (dbData.orderStatus === "PAID" && dbData.bankReference) {
//                     newFundStatus = 1; // Approved
//                     updateData.fund_status = 1;
//                     updateData.utr_no = dbData.bankReference; // Store UTR

//                     // If status changed to approved, credit user wallet
//                     if (transaction.fund_status !== 1) {
//                         await creditUserWallet(transaction.userDB_id, transaction.amount, transaction._id);
//                     }
//                 } 
//                 else if (dbData.status === "FAIL" || dbData.orderStatus === "FAIL") {
//                     newFundStatus = 2; // Failed
//                     updateData.fund_status = 2;
//                 }
//                 // If INPROCESS/PENDING/ACTIVE, keep as pending (0)
//             }

//             // Update transaction in database
//             await add_funds_module.findByIdAndUpdate(transactionId, updateData);

//             return res.json({
//                 success: true,
//                 msg: "Transaction status updated successfully",
//                 data: {
//                     newStatus: newFundStatus,
//                     orderStatus: statusResp.data?.orderStatus,
//                     bankReference: statusResp.data?.bankReference,
//                     gatewayStatus: statusResp.data?.status
//                 }
//             });
//         } else {
//             return res.json({
//                 success: false,
//                 msg: statusResp?.msg || "Unable to fetch status from payment gateway",
//                 gatewayResponse: statusResp
//             });
//         }

//     } catch (error) {
//         console.error("❌ Error refreshing PG transaction:", error);
//         return res.status(500).json({
//             success: false,
//             msg: "Error refreshing transaction status",
//             error: error.message
//         });
//     }
// };

// Helper function to credit user wallet
// async function creditUserWallet(userId, amount, transactionId) {
//     try {
//         // Update user wallet balance
//         await user_module.findByIdAndUpdate(
//             userId, 
//             { $inc: { wallet_balance: amount } },
//             { new: true }
//         );

//         // Create wallet history record
//         await wallet_trans_history_module.create({
//             userDB_id: userId,
//             transaction_id: transactionId,
//             amount: amount,
//             type: 'credit',
//             description: 'Wallet deposit via DollarBazar',
//             closing_balance: 0 // You might want to calculate this
//         });

//         console.log(`✅ Wallet credited for user ${userId} with amount ${amount}`);
//     } catch (error) {
//         console.error("❌ Error crediting wallet:", error);
//         throw error;
//     }
// }



// Add this new API for refreshing PG transaction status
// const refreshPGTransactionStatus = async (req, res) => {
//     try {
//         const { transactionId } = req.body;

//         // Find the transaction
//         const transaction = await add_funds_module.findById(transactionId);
//         if (!transaction) {
//             return res.status(404).json({ success: false, msg: "Transaction not found" });
//         }

//         // Only allow refresh for auto transactions (deposit_type = 1)
//         if (transaction.deposit_type !== 1) {
//             return res.status(400).json({ success: false, msg: "Only auto PG transactions can be refreshed" });
//         }

//         // Call payment gateway API to check status
//         // This is a placeholder - implement based on your payment gateway
//         const gatewayStatus = await checkPaymentGatewayStatus(transaction.txn_ref);

//         if (gatewayStatus) {
//             // Update transaction status based on gateway response
//             await add_funds_module.findByIdAndUpdate(transactionId, {
//                 fund_status: gatewayStatus.fund_status,
//                 gateway_response: gatewayStatus.response
//             });

//             return res.json({
//                 success: true,
//                 msg: "Transaction status updated successfully",
//                 newStatus: gatewayStatus.fund_status
//             });
//         } else {
//             return res.json({
//                 success: false,
//                 msg: "Unable to fetch status from payment gateway"
//             });
//         }

//     } catch (error) {
//         console.error("Error refreshing PG transaction:", error);
//         return res.status(500).json({
//             success: false,
//             msg: "Error refreshing transaction status"
//         });
//     }
// };

// Placeholder function - implement based on your payment gateway
// const checkPaymentGatewayStatus = async (transactionRef) => {
//     // Implement actual payment gateway API call here
//     // This should return { fund_status: 0/1/2, response: gateway_response }

//     // Mock implementation
//     return {
//         fund_status: 1, // 1 for approved
//         response: {
//             status: "success",
//             message: "Payment completed",
//             timestamp: new Date().toISOString()
//         }
//     };
// };




// 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 from = req.body.from;
//         const to = req.body.to;
//         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;

//         const startDate = moment_timeZone.tz(from?.trim(), 'Asia/Kolkata').clone().startOf('day').toDate();
//         const endDate = moment_timeZone.tz(to?.trim(), 'Asia/Kolkata').clone().endOf('day').toDate();

//         console.log("start end date-", startDate, endDate)

//         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 (startDate && endDate) {
//             statusFilter.insert_date = { $gte: startDate, $lte: endDate }
//         }

//         console.log("filter-", statusFilter)
//         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
//                 ? 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 {
        console.log("auto fund req body-", req.body)
        const depositDB_id = (req?.body?.depositDB_id || "").trim();
        const RefNo = (req?.body?.approveRefNo || "").trim();

        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: "No data found with respect to entered Ref. No..." })
            }
            console.log(refData.userDB_id, "ref id -", depositDB_id)

            if (refData && refData._id != depositDB_id) {

                const mockReq = {
                    body: {
                        depositDB_id: depositDB_id,
                        reject_remark: "Entered Reference number already in used"
                    }
                };

                const mockRes = {
                    json: (data) => {
                        // Return the rejection response instead of continuing with acceptance
                        return res.status(200).json({
                            success: false,
                            ...data
                        });
                    },
                    status: (code) => {
                        return {
                            json: (data) => {
                                return res.status(code).json({
                                    success: false,
                                    ...data
                                });
                            }
                        };
                    }
                };

                // Call the existing reject function
                return await rejectAutoFundRequest(mockReq, mockRes);
                // return res.status(200).json({ success: false, msg: "Reference 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");

            // await sendFBNotification(
            //     `Deposit amount`,
            //     `Admin approved your deposit request for deposit amount ${request?.amount}`,
            //     '',
            //     {} // no res → internal call
            // );

            // }

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

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

            const adminData = req.admin || null;
            console.log("🚀 ~ revertGalidisswarSingleBid ~ adminData:", adminData)
            console.log("🚀 ~ revertGalidisswarSingleBid ~ adminData:", adminData)
            if (!adminData || !adminData._id) {
                return res.status(401).json({ success: false, msg: 'Admin not found' });
            }

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

            };

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


            // CORRECT WAY — Pass only the user _id (as string or ObjectId)
            await sendFBNotification(
                `Deposit Approved!`,
                `Your deposit of ₹${request.amount} has been credited to your wallet.`,
                request.userDB_id._id.toString(),  // ← This is correct
                {} // internal call
            );

            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 (depositDB_id, reject_remark) => {
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');
        console.log("🚀 ~ rejectAutoFundRequest ~ request:", request)
        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()


        await sendFBNotification(
            `Rejected Deposit Request!`,
            `Your deposit request of ₹${request.amount} was rejected due to ${reject_remark}.`,
            request.userDB_id._id.toString(),
            {}
        );


        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",
            "mobile",
            "amount",
            "tx_request_number",
            "payment_method",
            "remark",
            "insert_date",
            "fund_payment_receipt",
            "withdraw_type",
            "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 = {};

        console.log("skip-", start, limit, start * limit)
        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' });
//     }
// };

// running perfect without the payout 22/11/2025

// 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();



//                 if (req?.admin) {

//                     await admin_module.findByIdAndUpdate(
//                         req.admin._id,
//                         { $inc: { wallet_amount: Number(updatedRequest.amount) } },
//                         { new: true }
//                     );

//                 }





//                 // 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' });
//     }
// };


// approveWithdrawRequest with payout

// const approveWithdrawRequest = async (req, res) => {
//     try {
//         const { withdraw_reqDB_id = "", remark = "", payment_method = "", action = 1 } = req.body || {};

//         // Validation
//         if (!withdraw_reqDB_id || !remark) {
//             return res.status(400).json({ success: false, msg: "withdraw_reqDB_id & remark required" });
//         }

//         const withdrawRequest = await withdraw_fund_request_module
//             .findById(withdraw_reqDB_id)
//             .populate("userDB_id");

//         if (!withdrawRequest) return res.status(400).json({ success: false, msg: "Request not found" });

//         const user = withdrawRequest.userDB_id;

//         // Reject Flow
//         if (action === 2) {
//             withdrawRequest.fund_status = 2;
//             withdrawRequest.remark = remark;
//             await withdrawRequest.save();

//             await user_notification_module.create({
//                 userDB_id: user._id,
//                 msg: `Withdraw of ₹${withdrawRequest.amount} rejected. Reason: ${remark}`,
//             });

//             return res.json({ success: true, msg: "Withdraw rejected successfully" });
//         }

//         // Step 1: CHECK WALLET BEFORE API CALL
//         if (user.wallet_balance < withdrawRequest.amount) {
//             return res.status(400).json({
//                 success: false,
//                 msg: `Insufficient balance. Required ${withdrawRequest.amount}, Available ${user.wallet_balance}`,
//             });
//         }

//         // Step 2: AUTHENTICATE → GET TOKENS
//         const { apiToken, idToken } = await authenticateQPay(withdrawRequest);
//         if (!apiToken) return res.status(400).json({ success: false, msg: "Authentication failed" });

//         // Step 3: CALL PAYOUT API
//         const payoutRes = await sendPayout(withdrawRequest, apiToken, idToken);

//         // Save initial gateway response
//         withdrawRequest.gateway_status = "PENDING";
//         withdrawRequest.gateway_txn_id = payoutRes?.data?.txnId || "";
//         withdrawRequest.bank_rrn = payoutRes?.data?.bankRefId || "";
//         await withdrawRequest.save();

//         // Step 4: STATUS CHECK (after payout request)
//         const finalStatus = await checkTransactionStatus(
//             withdrawRequest.tx_request_number,
//             apiToken,
//             idToken
//         );

//         let status = finalStatus?.metaInfo?.status || "PENDING";

//         // UPDATE DB BASED ON FINAL STATUS
//         if (status === "DONE") {
//             // SUCCESS → Deduct wallet
//             user.wallet_balance -= withdrawRequest.amount;
//             await user.save();

//             withdrawRequest.fund_status = 1;
//             withdrawRequest.gateway_status = "SUCCESS";
//             withdrawRequest.bank_rrn = finalStatus.metaInfo.bankRefId;
//             withdrawRequest.save();

//             return res.json({
//                 success: true,
//                 msg: "Withdraw SUCCESS",
//                 status,
//                 bankRefId: finalStatus.metaInfo.bankRefId,
//                 txnId: finalStatus.metaInfo.txnId,
//             });
//         }

//         if (status === "FAIL") {
//             withdrawRequest.fund_status = 3; // failed
//             withdrawRequest.gateway_status = "FAILED";
//             withdrawRequest.save();

//             return res.json({
//                 success: false,
//                 msg: "Withdraw FAILED",
//                 status,
//             });
//         }

//         // PENDING
//         withdrawRequest.fund_status = 4; // your code: pending verification
//         withdrawRequest.gateway_status = "PENDING";
//         await withdrawRequest.save();

//         return res.json({
//             success: true,
//             msg: "Withdraw Pending Confirmation",
//             status,
//         });

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

// second update with payout

// const approveWithdrawRequest = async (req, res) => {
//   try {
//     const { withdraw_reqDB_id, action, remark, payment_method } = req.body;

//     const record = await withdraw_fund_request_module.findById(withdraw_reqDB_id);
//     if (!record) return res.json({ success: false, msg: "Request not found" });

//     const user = await User.findById(record.userDB_id);
//     if (!user) return res.json({ success: false, msg: "User not found" });

//     // Reject request
//     if (action === 2) {
//       record.fund_status = 2; // failed
//       record.remark = remark;
//       await record.save();
//       return res.json({ success: true, msg: "Withdraw rejected" });
//     }

//     // APPROVE FLOW STARTS HERE
//     if (payment_method === 1) {
//       // -------------------------------
//       // 1️⃣ MANUAL PAYMENT PROCESSING
//       // -------------------------------

//       if (user.wallet_balance < record.amount) {
//         return res.json({ success: false, msg: "User has insufficient balance" });
//       }

//       // Deduct wallet
//       user.wallet_balance -= record.amount;
//       await user.save();

//       // Create wallet transaction
//       await WalletTransaction.create({
//         user_id: user._id,
//         amount: record.amount,
//         type: "WITHDRAW",
//         mode: "MANUAL",
//         status: "SUCCESS",
//         description: "Manual withdraw approved by admin",
//       });

//       // Update request status
//       record.fund_status = 1; // completed
//       record.remark = remark;
//       record.payment_method = 1;
//       await record.save();

//       return res.json({ success: true, msg: "Manual withdraw approved successfully" });
//     }

//     // -------------------------------
//     // 2️⃣ PAYMENT GATEWAY PAYOUT
//     // -------------------------------
//     if (payment_method === 5) {

//       const payoutResponse = await worldpayPayout({
//         amount: record.amount,
//         userDetails: user,
//         referenceId: record.tx_request_number
//       });

//       if (payoutResponse.status === "FAILED") {
//         record.fund_status = 2;
//         record.remark = payoutResponse.message;
//         await record.save();

//         return res.json({ success: false, msg: "PG Payout failed" });
//       }

//       // Success
//       user.wallet_balance -= record.amount;
//       await user.save();

//       await WalletTransaction.create({
//         user_id: user._id,
//         amount: record.amount,
//         type: "WITHDRAW",
//         mode: "WORLDPAY",
//         utr: payoutResponse.utr,
//         status: "SUCCESS",
//         description: "Withdraw sent through WorldPay",
//       });

//       record.fund_status = 1; // completed
//       record.remark = remark;
//       record.utr = payoutResponse.utr;
//       record.payment_method = 5;
//       await record.save();

//       return res.json({ success: true, msg: "Withdrawal processed through payment gateway" });
//     }

//     return res.json({ success: false, msg: "Invalid payment method" });

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

// third time update for multi or bulk req. approval // comment on 24-Nov for implement the payout functinality
// const approveWithdrawRequest = async (req, res) => {
//     try {
//         const {
//             withdraw_reqDB_id = "",
//             ids = [],
//             action,
//             remark = "",
//             payment_method = "",
//         } = req.body;

//         const isBulk = Array.isArray(ids) && ids.length > 0;
//         const requestIds = isBulk ? ids : [withdraw_reqDB_id];

//         if (!remark) {
//             return res.json({ success: false, msg: "Remark is required" });
//         }

//         // Validate IDs
//         for (const id of requestIds) {
//             if (!mongoose.isValidObjectId(id)) {
//                 return res.json({ success: false, msg: `Invalid id: ${id}` });
//             }
//         }

//         let processed = [];
//         let failed = [];

//         for (const reqId of requestIds) {
//             try {
//                 const record = await withdraw_fund_request_module.findById(reqId);
//                 if (!record) {
//                     failed.push({ id: reqId, msg: "Request not found" });
//                     continue;
//                 }

//                 const user = await user_module.findById(record.userDB_id);
//                 if (!user) {
//                     failed.push({ id: reqId, msg: "User not found" });
//                     continue;
//                 }

//                 // -----------------------------
//                 // 1️⃣ REJECTION FLOW
//                 // -----------------------------
//                 if (action === 2) {
//                     record.fund_status = 2;
//                     record.remark = remark;
//                     await record.save();

//                     processed.push({ id: reqId, msg: "Rejected" });
//                     continue;
//                 }

//                 // (APPROVAL BELOW)
//                 const method = payment_method || record.payment_method;

//                 // -----------------------------
//                 // 2️⃣ MANUAL (payment_method = 1)
//                 // -----------------------------
//                 if (method === 1) {

//                     if (user.wallet_balance < record.amount) {
//                         failed.push({
//                             id: reqId,
//                             msg: "User has insufficient balance",
//                         });
//                         continue;
//                     }

//                     user.wallet_balance -= record.amount;
//                     await user.save();

//                     await WalletTransaction.create({
//                         user_id: user._id,
//                         amount: record.amount,
//                         type: "WITHDRAW",
//                         mode: "MANUAL",
//                         status: "SUCCESS",
//                         description: "Manual withdraw approved by admin",
//                     });

//                     record.fund_status = 1;
//                     record.remark = remark;
//                     record.payment_method = 1;
//                     await record.save();

//                     processed.push({ id: reqId, msg: "Manually Approved" });
//                     continue;
//                 }

//                 // -----------------------------
//                 // 3️⃣ QPay payout (payment_method = 5)


//                 // if (method === 5) {
//                 //     const payoutResponse = await dollarbazarPayout(
//                 //         record.amount,
//                 //         user,   // OR bank details if stored separately
//                 //         record.tx_request_number
//                 //     );

//                 //     if (payoutResponse.status === "FAILED") {
//                 //         record.fund_status = 2;
//                 //         record.remark = payoutResponse.message;
//                 //         await record.save();
//                 //         failed.push({ id: reqId, msg: payoutResponse.message });
//                 //         continue;
//                 //     }

//                 //     user.wallet_balance -= record.amount;
//                 //     await user.save();

//                 //     await wallet_trans_history_module.create({
//                 //         user_id: user._id,
//                 //         amount: record.amount,
//                 //         type: "WITHDRAW",
//                 //         mode: "PG-PAYOUT",
//                 //         utr: payoutResponse.utr,
//                 //         status: "SUCCESS",
//                 //         description: "Withdraw via DollarBazar Payout",
//                 //     });

//                 //     record.fund_status = 1;
//                 //     record.remark = remark;
//                 //     record.payment_method = 5;
//                 //     record.utr = payoutResponse.utr;
//                 //     await record.save();

//                 //     processed.push({ id: reqId, msg: "Approved via PG" });
//                 //     continue;
//                 // }


//                 if (payment_method === 7) {
//                     const bankDetails = getUserBankDetails();

//                     const payoutRes = await dollarbazarPayout(
//                         amount,
//                         bankDetails,
//                         withdraw.tx_request_number
//                     );

//                     if (payoutRes.status === "SUCCESS") {
//                         updateWithdrawToSuccess(utr = payoutRes.utr);
//                         deductBalance();
//                         saveWalletHistory();
//                         return success("Gateway payout successful");
//                     }

//                     updateWithdrawToFailed(reason = payoutRes.message)
//                     return error("Gateway payout failed");
//                 }


//                 // -----------------------------
//                 // ❌ INVALID METHOD
//                 // -----------------------------
//                 failed.push({ id: reqId, msg: "Invalid payment method" });

//             } catch (err) {
//                 failed.push({ id: reqId, msg: "Internal error", error: err.message });
//             }
//         }

//         return res.json({
//             success: true,
//             isBulk,
//             processed,
//             failed,
//             msg: isBulk
//                 ? `Bulk Processed: ${processed.length}, Failed: ${failed.length}`
//                 : processed.length > 0
//                     ? processed[0].msg
//                     : failed[0].msg,
//         });

//     } catch (e) {
//         console.log("Bulk Withdraw Error:", e);
//         return res.json({ success: false, msg: "Server Error" });
//     }
// };

// final after use corrent keys
const approveWithdrawRequest = async (req, res) => {
    try {
        const {
            withdraw_reqDB_id = "",
            ids = [],
            action,
            remark = "",
            payment_method = "",
        } = req.body;

        const isBulk = Array.isArray(ids) && ids.length > 0;
        const requestIds = isBulk ? ids : [withdraw_reqDB_id];

        if (!remark || (!payment_method && action == 1) || !requestIds.length > 0) {
            return res.json({ success: false, msg: "Required all parameters!" });
        }

        let processed = [];
        let failed = [];

        const adminInfo = req?.admin || await admin_module.findOne({ admin_type: 0 })
        console.log("adminInfo ", adminInfo)
        if (!adminInfo) {
            return res.status(400).json({ success: false, msg: "Admin data not foun" })
        }

        for (const reqId of requestIds) {
            try {
                const record = await withdraw_fund_request_module.findById(reqId);
                if (!record) {
                    failed.push({ id: reqId, msg: "Withdraw request not found" });
                    continue;
                }

                const user = await user_module.findById(record.userDB_id);
                if (!user) {
                    failed.push({ id: reqId, msg: "User not found" });
                    continue;
                }


                // --------------------------------------------
                // 1️⃣ REJECTION
                // --------------------------------------------
                if (payment_method === 2 || action == 2) {
                    record.fund_status = 2;
                    record.remark = remark;
                    await record.save();
                    processed.push({ id: reqId, msg: "Rejected" });
                    continue;
                }






                // --------------------------------------------
                // 2️⃣ MANUAL APPROVAL
                // --------------------------------------------
                if (payment_method === 1) {

                    console.log("=== MANUAL APPROVAL START ===");
                    console.log("Request ID:", reqId);
                    console.log("Current fund_status:", record.fund_status);
                    console.log("Payment method:", payment_method);
                    console.log("User wallet:", user.wallet_balance);
                    console.log("Amount:", record.amount);

                    if (user.wallet_balance < record.amount) {
                        console.log("INSUFFICIENT BALANCE");
                        failed.push({ id: reqId, msg: "Insufficient wallet balance" });
                        continue;
                    }




                    // Store wallet balance before deduction
                    const beforeWallet = user.wallet_balance;
                    console.log("Before wallet:", beforeWallet);

                    const adminData = await admin_module.findByIdAndUpdate(req?.admin?._id, { $inc: { wallet_amount: record.amount } })



                    // Deduct from user's wallet
                    user.wallet_balance -= record.amount;
                    await user.save();
                    console.log("After wallet deduction:", user.wallet_balance);

                    try {
                        // Create wallet transaction history
                        const walletTrans = await wallet_trans_history_module.create({
                            userDB_id: user._id,
                            amount: record.amount,
                            before_wallet: beforeWallet,
                            admin_name: adminInfo?.username,
                            admin_type: adminInfo?.admin_type,
                            transaction_type: 2,
                            transaction_note: `Manual Withdraw Approved By ${adminInfo?.username}`,
                            tx_request_number: record?.tx_request_number,
                            amount_status: 10,
                            payment_method : 0, // manual withdraw approved
                            status: "SUCCESS"
                        });
                        console.log("Wallet transaction created:", walletTrans._id);
                    } catch (error) {
                        console.log("Wallet transaction error:", error);
                        failed.push({ id: reqId, msg: "Transaction creation failed", error: error.message });
                        continue;
                    }

                    // Update withdraw request status
                    record.fund_status = 1;
                    record.payment_method = 0 ;
                    record.remark = remark || `Approved by ${adminInfo?.username} ( Manual )`;

                    const savedRecord = await record.save();
                    console.log("Withdraw request updated - New status:", savedRecord.fund_status);
                    console.log("=== MANUAL APPROVAL END ===");

                    processed.push({ id: reqId, msg: "Manually Approved" });
                    continue;
                }












                //last function
                // if (payment_method === 7) {
                //     const bankDetails = await user_bank_details_module.findOne({ userDB_id: user._id });
                //     console.log("🚀 ~ approveWithdrawRequest ~ bankDetails:", bankDetails)

                //     if (!bankDetails) {
                //         failed.push({ id: reqId, msg: "Bank details missing" });
                //         continue;
                //     }
                //     const payout = await doPayout(
                //         record.amount,
                //         bankDetails,
                //         record.tx_request_number
                //     );
                //     console.log("🚀 ~ approveWithdrawRequest ```````admin controller````` ~ payout:", payout)

                //     if (payout.status === "FAILED") {
                //         record.fund_status = 2;
                //         record.remark = payout.message;
                //         await record.save();
                //         user.wallet_balance += record.amount;
                //         await user.save();

                //         failed.push({ id: reqId, msg: payout.message });
                //         continue;
                //     }

                //     // SUCCESS
                //     user.wallet_balance -= record.amount;
                //     await user.save();

                //     const adminData = await admin_module.findByIdAndUpdate(req?.admin?._id, { $inc: { wallet_amount: record.amount } })

                //     await wallet_trans_history_module.create({
                //         userDB_id: user._id,
                //         amount: record.amount,
                //         transaction_type: 2,
                //         transaction_note: "Withdraw via DollarBazar Payout",
                //         utr: payout.utr,
                //         status: "SUCCESS"
                //     });



                //     record.fund_status = 1;
                //     record.payment_method = 7;
                //     record.utr = payout.utr;
                //     record.remark = remark;
                //     await record.save();

                //     processed.push({ id: reqId, msg: "Payout Successful", utr: payout.utr });
                //     continue;
                // }






                if (payment_method === 7 || payment_method === 8) {
                    const bankDetails = await user_bank_details_module.findOne({ userDB_id: user._id });
                    console.log("🚀 ~ approveWithdrawRequest ~ bankDetails:", bankDetails);

                    if (!bankDetails) {
                        failed.push({ id: reqId, msg: "Bank details missing" });
                        continue;
                    }

                    // Use your existing PayoutManager
                    const payoutManager = require('../services/payoutManager');
                    
                    const payout = await payoutManager.processPayout(
                        record.amount,
                        bankDetails,
                        record.tx_request_number,
                        payment_method
                    );
                    
                    console.log("🚀 Payout Result:", payout);

                    if (payout.status === "FAILED") {
                        record.fund_status = 2;
                        record.remark = payout.message;
                        await record.save();
                        
                        failed.push({ id: reqId, msg: payout.message });
                        continue;
                    }

                    const adminData = await admin_module.findByIdAndUpdate(req?.admin?._id, { 
                        $inc: { wallet_amount: record.amount } 
                    });
                    // SUCCESS
                    user.wallet_balance -= record.amount;
                    await user.save();


                    // For DollarBazar: utr field, for ProtonPay: payoutId field
                    let utr = "";
                    if (payment_method === 7) {
                        utr = payout.utr || payout.tnxId || "";
                    } else if (payment_method === 8) {
                        utr = payout.payoutId || "";
                    }

                    // await wallet_trans_history_module.create({
                    //     userDB_id: user._id,
                    //     amount: record.amount,
                    //     transaction_type: 2,
                    //     transaction_note: `Withdraw via ${payment_method === 7 ? 'DollarBazar' : 'ProtonPay'} Payout`,
                    //     utr: utr,
                    //     status: "SUCCESS"
                    // });

                    record.fund_status = 1;
                    record.payment_method = payment_method;
                    record.utr = utr;
                    if (payment_method === 8) {
                        record.bankReference = payout.payoutId || "";
                    }
                    record.remark = remark;
                    await record.save();

                    processed.push({ 
                        id: reqId, 
                        msg: "Payout Successful", 
                        utr: utr,
                        gateway: payment_method === 7 ? 'DollarBazar' : 'ProtonPay'
                    });
                    continue;
                }



                failed.push({ id: reqId, msg: "Invalid payment method" });

            } catch (err) {
                failed.push({ id: reqId, msg: "Internal error", error: err.message });
            }
        }

        return res.json({
            success: true,
            isBulk,
            processed,
            failed,
            msg: `Processed: ${processed.length}, Failed: ${failed.length}`
        });

    } catch (e) {
        console.log("Error:", e);
        return res.json({ success: false, msg: "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 {
        const updateData = req?.body;
        console.log("🚀 ~ addAdminFixValues_with_maintainence ~ req.body:", req.body)

        // Validate required fields and set defaults if missing
        const validatedData = {
            app_id: 1,
            min_deposite: updateData.min_deposite || 10,
            max_deposite: updateData.max_deposite || 2000,
            min_withdrawal: updateData.min_withdrawal || 10,
            max_withdrawal: updateData.max_withdrawal || 2000,
            withdrawLimit: updateData.withdrawLimit || 0,
            min_transfer: updateData.min_transfer || 50,
            max_transfer: updateData.max_transfer || 10000,
            min_bid_amount: updateData.min_bid_amount || 10,
            max_bid_amount: updateData.max_bid_amount || 50000,
            welcome_bonus: updateData.welcome_bonus || 20,
            global_batting_status: updateData.global_batting_status || 0,
            app_maintainence_msg: updateData.app_maintainence_msg || "We are working on this page, please try again after",
            maintainence_msg_status: updateData.maintainence_msg_status || 0,
            marquee: updateData.marquee || "Welcome on AL786 !",
            user_refer_bonus: updateData.user_refer_bonus || 2,
            agent_refer_bonus: updateData.agent_refer_bonus || 10,
            withdraw_open_time: updateData.withdraw_open_time || "12:30",
            withdraw_close_time: updateData.withdraw_close_time || "03:30",
            homescreen_text: updateData.homescreen_text || "THIS IS A DEMO APP, DO NOT DEPOSIT ANY MONEY",
            refer_reward_status: updateData.refer_reward_status || 1,
            refer_self_reward: updateData.refer_self_reward || 8,
            refer_new_user_reward: updateData.refer_new_user_reward || 10,
            starline_enable: updateData.starline_enable || 1,
            delhi_enable: updateData.delhi_enable || 1,
            share_link: updateData.share_link || "https://google.com",
            withdraw_video_link: updateData.withdraw_video_link || "-",
            archive_history_days: updateData.archive_history_days || 30,
            withdrawLimitChangeRemark: updateData.withdrawLimitChangeRemark || "Updated via admin panel",
            userManualPaymentMode: updateData?.userManualPaymentMode || 0,
            userPgPaymentMode: updateData?.userPgPaymentMode || 0,
            autoWithdrawalStatus: updateData?.autoWithdrawalStatus || 0,
            autoWithdrawPgType: updateData?.autoWithdrawPgType || 0,
            autoWithdrawalMinAmount: updateData?.autoWithdrawalMinAmount || 0,
            autoWithdrawalMaxAmount: updateData?.autoWithdrawalMaxAmount || 0,

        };

        // Find and update or create new document
        let fixValues = await fix_values_module.findOneAndUpdate(
            { app_id: 1 },
            { $set: validatedData },
            {
                new: true,
                upsert: true,
                runValidators: true,
                setDefaultsOnInsert: true
            }
        );

        res.json({
            success: true,
            data: fixValues,
            message: "Settings updated successfully"
        });
    } catch (error) {
        console.error("Error updating fix values:", error);
        res.status(500).json({
            success: false,
            message: "Internal server error: " + error.message
        });
    }
};

const getFixValue = async (req, res) => {
    try {
        let fixValues = await fix_values_module.findOne({ app_id: 1 });
        console.log("🚀 ~ getFixValue ~ fixValues:", fixValues)

        // If no document exists, create one with default values
        if (!fixValues) {
            fixValues = new fix_values_module({
                app_id: 1,
                // All defaults will be applied automatically from schema
            });
            await fixValues.save();
        }

        res.json({
            success: true,
            data: fixValues
        });
    } catch (error) {
        console.error("Error getting fix values:", error);
        res.status(500).json({
            success: false,
            message: "Internal server error: " + error.message
        });
    }
};






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?.imageDB_id;
        // console.log("req.body", req.body)

        console.log("IMAGEID-", imageId, req?.body?.imageDB_id)
        // Find the image first
        const image = await slider_images_module.find({ _id: imageId });

        if (!image) {
            return res.json({ success: false, msg: "Image not found" });
        }
        console.log("IMAGE-", image)

        // 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 = {};

        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);
        // console.log("🚀 ~ subAdminListGridData ~ totalFiltered:", totalFiltered)
        console.log("🚀 ~ subAdminListGridData ~ searchQuery:", searchQuery)

        const results = await admin_module.find(searchQuery)
        // .sort({ [orderField]: orderDir })
        // .skip(skip)
        // .limit(limit)
        // .lean();
        // console.log("🚀 ~ subAdminListGridData ~ results:", results)

        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 || '',
            wallet_amount: rs?.wallet_amount || 0,
            commission: rs.commission || ''
        }));

        res.json({
            success: true,
            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 = '',
            wallet_amount = '',
        } = 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);
        wallet_amount = Number(wallet_amount);
        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, wallet_amount });

        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 bellNotificationList = 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 user_notification_module.countDocuments(searchQuery);

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

        const data = results.map((rs) => ({
            _id: rs._id,
            notice_title: rs.title,
            notice_msg: rs.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 addBellNotification = 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 userNotificationData = {
            title: notice_title.replace(/\b\w/g, c => c.toUpperCase()),
            msg: notice_msg,
        };

        // noticeData = await notice_module.create(noticeData);
        userNotificationData = await user_notification_module.create(userNotificationData);

        return res.json({
            success: true,
            msg: 'Bell Notification Successfully Added.',
            _id: userNotificationData._id,
            notice_title: userNotificationData.notice_title,
            notice_msg: userNotificationData.notice_msg,
            last_update: `${formatDateToDDMMYYYY(userNotificationData.last_update)} , ${get12HoursTimeFromISO(userNotificationData.last_update)}`,
            insert_date: `${formatDateToDDMMYYYY(userNotificationData.insert_date)} , ${get12HoursTimeFromISO(userNotificationData.insert_date)}`,
        });

    } catch (error) {
        console.error('Error in addBellNotification:', 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 addBellNotification:', 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 user_notification_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 (tokens, title, message) => {
    try {
        if (!title) throw new Error("Notification title missing");
        if (!message) throw new Error("Notification message missing");

        const payload = {
            notification: {
                title: title,
                body: message
            },
            tokens: tokens
        };

        return await admin.messaging().sendEachForMulticast(payload);

    } catch (err) {
        console.error("Notification error:", err);
        throw err;  // send back to controller
    }
};
// const User = require("../models/User"); // your user model
// const admin = require("../helper/firebase"); // your firebase-admin init

//last final before the change  for internal calling this function for send result declare notification
// const sendFBNotification = async (title, message) => {
//     try {
//         // const { title, message } = req.body;
//         // console.log("🚀 sendFBNotification ~ req.body:", req.body)

//         // Validate required fields
//         if (!title) return res.status(400).json({ error: "title missing" });
//         if (!message) return res.status(400).json({ error: "message missing" });

//         // Fetch all users with valid tokens
//         const users = await user_module.find(
//             {
//                 status: 1,
//                 firebaseToken: { $exists: true, $ne: "" }
//             },
//             { firebaseToken: 1 }
//         );

//         // Extract tokens and remove duplicates/empty ones
//         let allTokens = users
//             .map(user => user.firebaseToken)
//             .filter(token => token && token.trim() !== "");

//         // Remove duplicates
//         allTokens = [...new Set(allTokens)];

//         // Final check
//         if (allTokens.length === 0) {
//             return res.status(400).json({ error: "No valid FCM tokens found" });
//         }

//         console.log(`🔥 Sending to ${allTokens.length} users`);

//         // Create payload and send
//         const payload = {
//             notification: {
//                 title,
//                 body: message
//             },
//             tokens: allTokens
//         };

//         const result = await admin.messaging().sendEachForMulticast(payload);

//         return res.json({
//             success: true,
//             message: "Notification sent successfully",
//             totalTokens: allTokens.length,
//             successCount: result.successCount,
//             failureCount: result.failureCount
//         });

//     } catch (err) {
//         console.error("Notification error:", err);
//         return res.status(500).json({ error: err.message });
//     }
// };

// utils/sendNotification.js  (or inside your admin controller file)


// with perticular user or deposit withdrw
// BEST VERSION — Supports both: All users OR Single user
const sendFBNotification = async (title, body, userId = null, options = {}) => {
    try {
        const isApiCall = !!options.res;
        const res = options.res;

        // Validate
        if (!title || !body) {
            const error = "Title and body are required";
            if (isApiCall) return res.status(400).json({ success: false, error });
            throw new Error(error);
        }

        let allTokens = [];

        if (userId) {
            // === SEND TO SINGLE USER ===
            let userIdObj;
            try {
                userIdObj = mongoose.Types.ObjectId.isValid(userId)
                    ? new mongoose.Types.ObjectId(userId)
                    : null;
            } catch {
                userIdObj = null;
            }

            if (!userIdObj) {
                console.log("Invalid userId for notification:", userId);
                if (isApiCall) return res.status(400).json({ success: false, error: "Invalid user ID" });
                return { success: false, skipped: true, message: "Invalid user ID" };
            }

            const user = await user_module.findOne(
                { _id: userIdObj, status: 1, firebaseToken: { $exists: true, $ne: "" } },
                { firebaseToken: 1 }
            );

            if (user?.firebaseToken) {
                allTokens = [user.firebaseToken.trim()];
            }
        } else {
            // === SEND TO ALL USERS ===
            const users = await user_module.find(
                { status: 1, firebaseToken: { $exists: true, $ne: "" } },
                { firebaseToken: 1 }
            );

            allTokens = [...new Set(
                users
                    .map(u => u.firebaseToken?.trim())
                    .filter(t => t && t.length > 0)
            )];
        }

        console.log("🚀 ~ sendFBNotification ~ allTokens:", allTokens)


        if (allTokens.length === 0) {
            const msg = userId ? "User has no FCM token" : "No valid FCM tokens found";
            console.log("⚠️", msg);
            if (isApiCall) return res.status(400).json({ success: false, error: msg });
            return { success: true, skipped: true, message: msg };
        }

        console.log(` Sending FCM to ${allTokens.length} device(s)`);

        const payload = {
            notification: { title, body },
            tokens: allTokens
        };

        const response = await admin.messaging().sendEachForMulticast(payload);

        const result = {
            success: true,
            totalTokens: allTokens.length,
            successCount: response.successCount,
            failureCount: response.failureCount,
        };

        if (isApiCall) {
            return res.json(result);
        }

        return result;

    } catch (err) {
        console.error("FCM Notification Error:", err.message);

        if (options.res) {
            return options.res.status(500).json({
                success: false,
                error: err.message || "Failed to send notification"
            });
        }
        throw err;
    }
};



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();

        // Create a mapping for sort fields to handle nested fields properly
        const sortFieldMap = {
            "game_name": "game_name",
            "open_time": "weekdayData.open_time",
            "close_time": "weekdayData.close_time",
            "status": "status",
            "market_status": "weekdayData.weekday_status"
        };

        const sortField = sortFieldMap[orderField] || "game_name";

        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
            },
            {
                $addFields: {
                    sortOpenTime: { $ifNull: ["$weekdayData.open_time", new Date(0)] },
                    sortCloseTime: { $ifNull: ["$weekdayData.close_time", new Date(0)] },
                    sortMarketStatus: { $ifNull: ["$weekdayData.weekday_status", 0] }
                }
            },
            {
                $sort: {
                    [sortField === "weekdayData.open_time" ? "sortOpenTime" :
                        sortField === "weekdayData.close_time" ? "sortCloseTime" :
                            sortField === "weekdayData.weekday_status" ? "sortMarketStatus" :
                                sortField]: 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) => {
    // console.log("body-", req.body)
    try {
        // fields arrays have two wallet_balance and last_update because this api is called from two component (user management and view wallet) and both have different index for wallet balance and last_update
        let fields = [
            "S.no",
            "user_name",
            "mobile",
            "wallet_balance",
            "last_update",
            "insert_date",
            "last_update",
            "wallet_balance",
            "status",
            "Action",
        ]

        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
        const type = req?.body?.selectedstatus || 'All' //|| req.params.status.slice(1)
        console.log("field-", orderField)
        let searchQuery = {};
        console.log(req.body, type)
        if (searchValue) {
            const isNumeric = !isNaN(searchValue);
            const regexValue = `^${searchValue}`;

            if (isNumeric) {
                searchQuery = {
                    $or: [
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$user_name" },
                                    regex: regexValue,
                                    options: "i"
                                }
                            }
                        },
                        {
                            $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)
        }
        // console.log("searchQ - ",searchQuery)
        const totalFiltered = await user_module.countDocuments(searchQuery);

        if (type !== 'All') {
            // filter.status = type == 'Active' ? 1 : 0 
            searchQuery.status = type == 'Active' ? 1 : 0
        }
        const results = await user_module.find(searchQuery)
            .sort({ [orderField]: orderDir })
            .skip(skip)
            .limit(limit)
            .lean();
        console.log("🚀 ~ userListGridData ~ results:", results)

        // 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,
            security_pin: rs?.security_pin,
            insert_date: `${formatDateToDDMMYYYY(rs.insert_date)} , ${get12HoursTimeFromISO(rs.insert_date)}`,
        }));

        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 = "", note = "" } = 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' });
        }
        const admin = req?.admin;
        console.log("admin", admin)




        if (amount > admin?.wallet_amount) {
            return res.status(400).json({ success: false, msg: 'Insufficient admin wallet balance' });
        }
        await user_module.updateOne({ _id: userDB_id }, { $inc: { wallet_balance: amount } });


        await admin_module.updateOne({ _id: admin._id }, { $inc: { wallet_amount: -amount } });

        const request_number = getUserRandomToken();

        await wallet_trans_history_module.create({
            userDB_id,
            amount,
            transaction_type: 1,
            transfer_note: note ? toStr(note) : 'Amount Added By Admin',
            transaction_note: 'Amount Added By Admin',
            amount_status: 1,
            admin_type: admin?.admin_type,
            admin_name: admin?.admin_type == 0 ? "Auto/Self" : admin?.username,

            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();
        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 {
            length = 10,
            start = 0, // Changed from 1 to 0 to match frontend expectation
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            date,
            gameDB_id,
            userDB_id
        } = req.body;

        const fields = [
            "#",
            "user_name",
            "mobile",
            "session",
            "game_name",
            "digits",
            "points",
            "insert_date",
            "Actions",
        ];

        const limit = parseInt(length);
        const page = parseInt(start);

        // FIX: Ensure skip is never negative
        const skip = Math.max(0, page); // Directly use page as skip since frontend sends start position

        const orderField = fields[fieldIndex] || "bid_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        console.log("🔄 getStarlineBidRevertData ~ req.body:", {
            length, start, limit, page, skip, searchTerm
        });

        if (!date || !gameDB_id) {
            return res.status(400).json({
                success: false,
                msg: "Date and Game ID are required"
            });
        }

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

        // Convert date to proper range
        const bidDateStart = moment_timeZone.tz(date.trim(), ["DD-MM-YYYY", "YYYY-MM-DD"], "Asia/Kolkata").startOf('day').toDate();
        const bidDateEnd = moment_timeZone.tz(date.trim(), ["DD-MM-YYYY", "YYYY-MM-DD"], "Asia/Kolkata").endOf('day').toDate();

        console.log("📅 Starline date range:", bidDateStart, bidDateEnd);

        const matchFilter = {
            bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
            pay_status: 0,
        };
        if (gameDB_id !== 'all') {
            matchFilter.gameDB_id = new mongoose.Types.ObjectId(gameDB_id)

        }
        // ADD USER FILTERING
        if (userDB_id && mongoose.isValidObjectId(userDB_id)) {
            matchFilter.userDB_id = new mongoose.Types.ObjectId(userDB_id);
            console.log("🔍 Filtering starline by user:", userDB_id);
        }

        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,
                    points: 1,
                    bid_tx_id: 1,
                    bid_date: 1,
                    insert_date: 1,
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile"
                }
            },
        ];

        // Enhanced search filter
        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
                                }
                            }
                        }
                    ]
                }
            });
        }

        // Get total count first
        const totalCountPipeline = [...basePipeline, { $count: "total" }];
        const totalCountArr = await starline_bid_history_module.aggregate(totalCountPipeline);
        const totalFiltered = totalCountArr[0]?.total || 0;

        // Get paginated results with proper skip
        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        // Get all IDs for selection
        const pipelineForResultIds = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } }
        ];

        console.log(`📊 Starline query - Skip: ${skip}, Limit: ${limit}, Total: ${totalFiltered}`);

        const [results, resultsIds] = await Promise.all([
            starline_bid_history_module.aggregate(pipelineWithPagination),
            starline_bid_history_module.aggregate(pipelineForResultIds),
        ]);

        const all_ids = resultsIds.map(v => v._id);

        // Format data
        const data = results.map((v, index) => {
            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: formatDateToDDMMYYYY(v.bid_date),
                insert_date: v.insert_date,
                user_name: v.user_name,
                userDB_id: v.userDB_id,
                mobile: v.mobile || "N/A",
                index: skip + index + 1
            };

            // Starline specific data formatting
            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...common,
                        market: 'Single Digit',
                        number: v.digits,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_digit: v.session === 'Close' ? v.digits : 'N/A',
                    };

                case 'Jodi Digit':
                    return {
                        ...common,
                        market: 'Jodi Digit',
                        number: v.digits,
                        open_digit: v.digits?.charAt(0) || 'N/A',
                        close_digit: v.digits?.charAt(1) || 'N/A',
                    };

                case 'Single Pana':
                case 'Double Pana':
                case 'Triple Pana':
                    return {
                        ...common,
                        market: v.pana,
                        number: v.digits,
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.digits : 'N/A',
                    };

                case 'Half Sangam':
                    return {
                        ...common,
                        market: 'Half Sangam',
                        number: `Digit: ${v.digits}, Pana: ${v.closedigits || 'N/A'}`,
                        open_digit: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                    };

                case 'Full Sangam':
                    return {
                        ...common,
                        market: 'Full Sangam',
                        number: `Open: ${v.digits}, Close: ${v.closedigits || 'N/A'}`,
                        open_pana: v.session === 'Open' ? v.digits : 'N/A',
                        close_pana: v.session === 'Close' ? v.closedigits : 'N/A',
                    };

                default:
                    return {
                        ...common,
                        market: v.pana || 'Unknown',
                        number: v.digits || 'N/A',
                        open_digit: 'N/A',
                        close_digit: 'N/A',
                        open_pana: 'N/A',
                        close_pana: 'N/A',
                    };
            }
        });

        console.log(`✅ Found ${data.length} starline records out of ${totalFiltered} total`);

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

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




const getgalidisswarBidRevertData = async (req, res) => {
    try {
        const {
            length = 10,
            start = 0,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            date,
            gameDB_id,
            userDB_id, // ADD THIS: User filter parameter
            get_all_data = false // ADD THIS: For "Refund All" functionality
        } = req.body;

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

        const limit = get_all_data ? 10000 : parseInt(length); // Large limit for "Refund All"
        const page = parseInt(start);
        const skip = !searchValue ? page : 0;
        const orderField = fields[fieldIndex] || "bid_date";
        const orderDir = parseInt(order);
        const searchTerm = searchValue?.trim() || '';

        console.log("🔍 getgalidisswarBidRevertData ~ req.body:", {
            gameDB_id, date, userDB_id, get_all_data, searchTerm
        });

        // if ((gameDB_id!=="" && !mongoose.isValidObjectId(gameDb_id)) || !date) {
        //     return res.status(400).json({ success: false, msg: 'Game ID and Date are required.' });
        // }

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

        // Build base match filter
        const matchFilter = {
            bid_date: { $gte: bidDateStart, $lte: bidDateEnd },
            // gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            pay_status: 0, // Only pending bids
        };

        if (gameDB_id != "all") {
            if (!mongoose.isValidObjectId(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(gameDB_id)
        }
        // ADD USER FILTERING
        if (userDB_id && mongoose.isValidObjectId(userDB_id)) {
            matchFilter.userDB_id = new mongoose.Types.ObjectId(userDB_id);
            console.log("🔍 Filtering by user:", userDB_id);
        }

        // Build aggregation pipeline
        const basePipeline = [
            {
                $match: matchFilter
            },
            {
                $lookup: {
                    from: 'users',
                    localField: 'userDB_id',
                    foreignField: '_id',
                    as: 'userData'
                }
            },
            {
                $unwind: {
                    path: '$userData',
                    preserveNullAndEmptyArrays: true
                }
            },
            {
                $addFields: {
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile"
                }
            },
            {
                $project: {
                    _id: 1,
                    points: 1,
                    userDB_id: 1,
                    bid_date: 1,
                    user_name: 1,
                    mobile: 1,
                    game_name: 1,
                    pana: 1,
                    session: 1,
                    digits: 1,
                    closedigits: 1,
                    type: 1,
                    bid_tx_id: 1
                }
            }
        ];

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

        // Create different pipelines based on requirements
        const pipelineWithPagination = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } },
            { $skip: skip },
            { $limit: limit }
        ];

        const pipelineForAllIds = [
            ...basePipeline,
            { $sort: { [orderField]: orderDir } }
        ];

        const pipelineForCount = [
            ...basePipeline,
            { $count: "total" }
        ];

        console.log(`📊 Executing queries: get_all_data=${get_all_data}, limit=${limit}, skip=${skip}`);

        // Execute parallel queries
        const [results, allIdsResult, totalCountArr] = await Promise.all([
            // Get paginated data or all data for refund all
            gali_disswar_bid_history_module.aggregate(
                get_all_data ? pipelineForAllIds : pipelineWithPagination
            ),
            // Get all IDs for selection functionality
            gali_disswar_bid_history_module.aggregate([
                ...basePipeline,
                { $project: { _id: 1 } }
            ]),
            // Get total count
            gali_disswar_bid_history_module.aggregate(pipelineForCount)
        ]);

        const totalFiltered = totalCountArr[0]?.total || 0;
        const all_ids = allIdsResult.map(item => item._id.toString());

        // Format dates and enhance data
        const formattedResults = results.map((item, index) => ({
            ...item,
            index: skip + index + 1,
            bid_date: formatDateToDDMMYYYY(item.bid_date),
            formatted_points: `₹${Number(item.points).toFixed(2)}`,
            // Add additional fields for frontend display
            display_type: item.type || item.pana || 'N/A',
            display_digits: item.digits || 'N/A',
            display_session: item.session || 'N/A'
        }));

        console.log(`✅ Found ${formattedResults.length} records out of ${totalFiltered} total`);

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            data: formattedResults,
            all_ids: get_all_data ? all_ids : [], // Only return all_ids if not get_all_data to avoid large responses
            limit,
            totalCount: totalFiltered
        });

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



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 ? 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 mainGamesIds = await games_module.find(
        //     { status: 1 },
        //     { _id: 1 }
        // ).lean();


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

        // if (mainGamesIdsArray.length > 0) {
        //     baseMatch.main_gameDB_id = { $in: mainGamesIdsArray };
        // }

        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 adminData = req.admin || null;
        // if (!adminData || !adminData._id) {
        //     return res.status(401).json({ success: false, msg: 'Admin not found' });
        // }


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

        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 getWalletTransactionArchiveHistory = async (req, res) => {
    try {
        const {
            length = 100,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            start_date,
            end_date,
            transaction_type,
            min_amount
        } = req.body;

        const fields = [
            "user_name",
            "mobile",
            "amount",
            "transaction_type",
            "transaction_note",
            "amount_status",
            "tx_request_number",
            "insert_date",
        ];

        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 getWalletTransactionArchiveHistory", req.body);

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

        // Parse dates (adjust format as needed)
        const startDate = new Date(start_date);
        const endDate = new Date(end_date);
        endDate.setHours(23, 59, 59, 999); // End of day

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

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

        const matchFilter = {
            insert_date: { $gte: startDate, $lte: endDate },
        };

        if (transaction_type && transaction_type !== "") {
            matchFilter.transaction_type = parseInt(transaction_type);
        }

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

        const basePipeline = [
            { $match: matchFilter },
            {
                $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 (searchTerm) {
            const regex = new RegExp(`^${searchTerm}`, "i");
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: regex } },
                        { mobile: { $regex: regex } },
                        { transaction_note: { $regex: regex } },
                        { transfer_note: { $regex: regex } },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$amount" },
                                    regex
                                }
                            }
                        },
                        {
                            $expr: {
                                $regexMatch: {
                                    input: { $toString: "$tx_request_number" },
                                    regex
                                }
                            }
                        },
                    ]
                }
            });
        }

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

        console.log("Pipeline for wallet archive:", JSON.stringify(pipelineWithPagination, null, 2));

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

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

        // Format dates for display
        const data = results.map((transaction) => ({
            ...transaction,
            insert_date: `${formatDateToDDMMYYYY(transaction.insert_date)} , ${get12HoursTimeFromISO(transaction.insert_date)}`,
        }));

        console.log(`✅ Found ${data.length} wallet archive records`);

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

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











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,
                    session: 1,
                    pana: 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 = "", note = "" } = 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);
        const before_Wallet_amount = user?.wallet_balance || 0;

        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 }
        );


        const admin = req?.admin;
        console.log("🚀 ~ withdrawBalanceUserWallet ~ admin:", admin)

        if (!admin || !admin._id) {
            return res.status(401).json({
                success: false,
                msg: 'Admin not found'
            });
        }



        await admin_module.updateOne({ _id: admin._id }, { $inc: { wallet_amount: withdrawAmount } });

        // Add to wallet transaction history
        const request_number = uniqRandom();
        await wallet_trans_history_module.create(
            [{
                userDB_id,
                amount: withdrawAmount,
                transfer_note: note ? toStr(note) : 'Amount Added By Admin',
                transaction_type: 2, // 2 = Withdraw
                transaction_note: 'Amount Withdrawn By Admin',
                before_wallet: before_Wallet_amount,
                admin_type: admin?.admin_type,
                admin_name: admin?.admin_type == 0 ? "Auto/Self" : admin?.username,
                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 isStarlineDeleteProcessing = false;

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

    console.log("🚀 ~ starlineDeleteBids ~ req.body:", req.body)
    try {
        const { bid_id, user_id, amount } = req.body;

        console.log("🔄 revertSingleStarlineBid ~ req.body:", req.body);

        if (!bid_id || !user_id || !amount) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Bid ID, User ID and Amount are required"
            });
        }

        // Step 1: Find and delete the starline bid
        const bid = await starline_bid_history_module.findById(bid_id).session(session);
        if (!bid) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "Starline bid not found"
            });
        }

        console.log("🗑️ Deleting starline bid:", bid.bid_tx_id);
        await starline_bid_history_module.deleteOne({ _id: bid_id }).session(session);

        // Step 2: Add amount back to user wallet
        const user = await user_module.findById(bid.userDB_id).session(session);
        if (!user) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "User not found"
            });
        }

        const originalBalance = user.wallet_balance;
        user.wallet_balance += amount;
        await user.save({ session });

        console.log(`💰 Wallet updated: ${user.user_name} - ${originalBalance} -> ${user.wallet_balance}`);

        // Step 3: Delete original bid transaction using tx_request_number
        const deleteResult = await wallet_trans_history_module.deleteMany({
            tx_request_number: bid.bid_tx_id // Use tx_request_number instead of bid_tx_id
        }).session(session);

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} wallet transactions for starline bid: ${bid.bid_tx_id}`);

        // If no transactions were found/deleted, log it but don't fail
        if (deleteResult.deletedCount === 0) {
            console.log(`⚠️ No wallet transactions found for tx_request_number: ${bid.bid_tx_id}`);

            // Let's also try to find what transactions exist for this user
            const userTransactions = await wallet_trans_history_module.find({
                userDB_id: bid.userDB_id,
                amount_status: 5 // bid placed
            }).session(session);

            console.log(`🔍 Found ${userTransactions.length} bid transactions for user:`,
                userTransactions.map(t => ({
                    tx_request_number: t.tx_request_number,
                    amount: t.amount,
                    bid_tx_id: t.bid_tx_id // Check if this field exists
                }))
            );
        }

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

        return res.status(200).json({
            success: true,
            message: `Starline bid reverted successfully. Amount ₹${Number(amount).toFixed(2)} added back to wallet.`,
            data: {
                refundedAmount: Number(amount),
                userNewBalance: user.wallet_balance,
                bid_tx_id: bid.bid_tx_id,
                deletedTransactions: deleteResult.deletedCount
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertSingleStarlineBid", error);
        return res.status(500).json({
            success: false,
            message: "Failed to revert starline bid: " + error.message
        });
    }
};

// Separate endpoint for single bid delete
const starlineDeleteSingleBid = async (req, res) => {
    const { bid_id } = req.body;

    // Reuse the main function with single bid parameters
    req.body.bid_ids = bid_id;

    return starlineDeleteBids(req, res);
};



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

    try {
        const { bid_ids, bids_data } = req.body;

        console.log("🔄 revertMultipleStarlineBids ~ Processing", bid_ids?.length, "starline bids");

        if (!bid_ids || !Array.isArray(bid_ids) || bid_ids.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Starline Bid IDs are required"
            });
        }

        let totalRefunded = 0;
        let revertedCount = 0;
        const userSummary = {};

        // Step 1: Delete all starline bids first
        const deleteResult = await starline_bid_history_module.deleteMany({
            _id: { $in: bid_ids }
        }).session(session);

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} starline bids from database`);

        // Step 2: Process wallet updates for each user
        for (const bidData of bids_data) {
            const { userDB_id, amount } = bidData;

            if (!userSummary[userDB_id]) {
                userSummary[userDB_id] = {
                    user: await user_module.findById(userDB_id).session(session),
                    totalRefunded: 0
                };
            }

            const userData = userSummary[userDB_id];

            if (userData.user) {
                userData.totalRefunded += Number(amount);
                totalRefunded += Number(amount);
                revertedCount++;
            }
        }

        // Step 3: Update all user wallets
        for (const userId in userSummary) {
            if (userSummary[userId].user && userSummary[userId].totalRefunded > 0) {
                const originalBalance = userSummary[userId].user.wallet_balance;
                userSummary[userId].user.wallet_balance += userSummary[userId].totalRefunded;
                await userSummary[userId].user.save({ session });

                console.log(`💰 Wallet updated for ${userSummary[userId].user.user_name}: ${originalBalance} -> ${userSummary[userId].user.wallet_balance}`);
            }
        }

        // Step 4: Delete all original starline bid transactions
        const deletedTransactions = await wallet_trans_history_module.deleteMany({
            tx_request_number: { $in: bids_data.map(bid => bid.bid_tx_id) }
        }).session(session);

        console.log(`🗑️ Deleted ${deletedTransactions.deletedCount} wallet transactions for multiple starline bids`);

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

        // Prepare response
        const userRefundDetails = Object.keys(userSummary)
            .filter(userId => userSummary[userId].totalRefunded > 0)
            .map(userId => ({
                user_id: userId,
                user_name: userSummary[userId].user?.user_name || 'Unknown',
                refunded_amount: userSummary[userId].totalRefunded,
                new_balance: userSummary[userId].user?.wallet_balance || 0
            }));

        return res.status(200).json({
            success: true,
            message: `Successfully reverted ${revertedCount} starline bids. Total amount returned: ₹${totalRefunded.toFixed(2)}`,
            data: {
                revertedCount,
                totalRefunded,
                userRefundDetails,
                deletedBids: deleteResult.deletedCount,
                deletedTransactions: deletedTransactions.deletedCount
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertMultipleStarlineBids", error);
        return res.status(500).json({
            success: false,
            message: "Failed to revert starline bids: " + error.message
        });
    }
};















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));
        }
    }
};

// revert Galidsswar Single Bid
const revertGalidisswarSingleBid = async (req, res) => {
    // const session = await mongoose.startSession();
    // session.startTransaction();

    try {
        const { bid_id, user_id, amount, bid_date, gameDB_id } = req.body;

        console.log("🔄 revertGalidisswarSingleBid ~ req.body:", req.body);

        if (!bid_id || !user_id || !amount) {
            // await session.abortTransaction();
            // session.endSession();
            return res.status(400).json({
                success: false,
                message: "Bid ID, User ID and Amount are required"
            });
        }

        // Step 1: Find and delete the bid
        const bid = await gali_disswar_bid_history_module.findById(bid_id);
        if (!bid) {
            // await session.abortTransaction();
            // session.endSession();
            return res.status(404).json({
                success: false,
                message: "Bid not found"
            });
        }

        // Check if bid is already processed
        // if (bid.pay_status === 3) {
        //     await session.abortTransaction();
        //     session.endSession();
        //     return res.status(400).json({
        //         success: false,
        //         message: "Bid has already been reverted"
        //     });
        // }

        console.log("🗑️ deleting bid:", bid._id);
        await gali_disswar_bid_history_module.deleteOne({ _id: bid_id });



        // Step 2: Add amount back to user wallet

        const user = await user_module.findById(user_id);
        if (!user) {
            // await session.abortTransaction();
            // session.endSession();
            return res.status(404).json({
                success: false,
                message: "User not found"
            });
        }

        const originalBalance = user.wallet_balance;
        user.wallet_balance += Number(amount);
        await user.save();

        console.log(`💰 Wallet updated: ${user.user_name} - ${originalBalance} -> ${user.wallet_balance}`);

        // const transactionNote = `Bid reverted for ${bid.game_name || 'Galidisswar'} - ${bid.pana || bid.digits || 'N/A'}`;

        // await wallet_trans_history_module.create([{
        //     userDB_id: user_id,
        //     amount: Number(amount),
        //     transaction_type: 1, // Credit
        //     transaction_note: transactionNote,
        //     amount_status: 7, // Bid Refund
        //     tx_request_number: uniqRandom(15),
        //     created_date: new Date()
        // }], { session });

        // console.log(`📝 Created refund transaction for user: ${user.user_name}`);

        const adminData = req.admin || null;
        if (!adminData || !adminData._id) {
            return res.status(401).json({ success: false, msg: 'Admin not found' });
        }

        console.log("removied amount -", amount, "from admin -", adminData)
        await admin_module.findByIdAndUpdate(
            adminData._id,
            { $inc: { wallet_amount: -Number(amount) } },
            { new: true }
        )

        //  Step 3: Delete original bid transaction using tx_request_number
        const deleteResult = await wallet_trans_history_module.deleteMany({
            tx_request_number: bid.bid_tx_id // Use tx_request_number instead of bid_tx_id
        });

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} wallet transactions for bid: ${bid.bid_tx_id}`);

        // If no transactions were found/deleted, log it but don't fail
        if (deleteResult.deletedCount === 0) {
            console.log(`⚠️ No wallet transactions found for tx_request_number: ${bid.bid_tx_id}`);

            // Let's also try to find what transactions exist for this user
            const userTransactions = await wallet_trans_history_module.find({
                userDB_id: bid.userDB_id,
                amount_status: 5 // bid placed
            });

            console.log(`🔍 Found ${userTransactions.length} bid transactions for user:`,
                userTransactions.map(t => ({
                    tx_request_number: t.tx_request_number,
                    amount: t.amount,
                    bid_tx_id: t.bid_tx_id // Check if this field exists
                }))
            );
        }


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

        return res.status(200).json({
            success: true,
            message: `Bid reverted successfully. Amount ₹${Number(amount).toFixed(2)} added back to wallet.`,
            data: {
                refundedAmount: Number(amount),
                userNewBalance: user.wallet_balance,
                bid_id: bid_id
            }
        });

    } catch (error) {
        // await session.abortTransaction();
        // session.endSession();
        console.log("❌ Error in revertGalidisswarSingleBid", error);
        return res.status(500).json({
            success: false,
            message: "Failed to revert bid: " + error.message
        });
    }
};


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

    try {
        const { bid_ids, bids_data, gameDB_id, bid_revert_date } = req.body;

        console.log("🔄 revertGalidisswarMultipleBids ~ Processing", bid_ids?.length, "bids");

        if (!bid_ids || !Array.isArray(bid_ids) || bid_ids.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Bid IDs are required"
            });
        }

        // Step 1: First, fetch all bids to get their transaction IDs
        const bids = await gali_disswar_bid_history_module.find({
            _id: { $in: bid_ids }
        }).session(session);

        if (!bids || bids.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "No bids found"
            });
        }

        console.log(`📋 Found ${bids.length} bids to revert`);


        const adminData = req.admin || null;
        if (!adminData || !adminData._id) {
            return res.status(401).json({ success: false, msg: 'Admin not found' });
        }
        let totalRefunded = 0;
        let revertedCount = 0;
        const userSummary = {};

        // Step 2: Organize data by user and collect transaction IDs
        const bidTxIds = [];

        for (const bid of bids) {
            const userId = bid.userDB_id.toString();
            const amount = bid.points; // Use points instead of amount
            const bidTxId = bid.bid_tx_id;

            if (!userSummary[userId]) {
                userSummary[userId] = {
                    user: null,
                    totalRefunded: 0,
                    bidTxIds: []
                };
            }

            userSummary[userId].totalRefunded += Number(amount);
            userSummary[userId].bidTxIds.push(bidTxId);
            bidTxIds.push(bidTxId);
            totalRefunded += Number(amount);
            revertedCount++;
        }

        // Step 3: Fetch user data
        const userIds = Object.keys(userSummary);
        const users = await user_module.find({ _id: { $in: userIds } }).session(session);

        for (const user of users) {
            const userId = user._id.toString();
            if (userSummary[userId]) {
                userSummary[userId].user = user;
            }
        }

        // Step 4: Delete all bids
        const deleteResult = await gali_disswar_bid_history_module.deleteMany({
            _id: { $in: bid_ids }
        }).session(session);

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} bids from database`);

        // Step 5: Update all user wallets
        for (const userId in userSummary) {
            if (userSummary[userId].user && userSummary[userId].totalRefunded > 0) {
                const user = userSummary[userId].user;
                const originalBalance = user.wallet_balance;
                user.wallet_balance += userSummary[userId].totalRefunded;
                await user.save({ session });

                console.log(`💰 Wallet updated for ${user.user_name}: ${originalBalance} -> ${user.wallet_balance}`);
            }
        }

        // Step 6 : Updating admin wallet
        await admin_module.findByIdAndUpdate(
            adminData._id,
            { $inc: { wallet_amount: -Number(totalRefunded) } },
            { new: true }
        )

        // Step 7: Delete all original bid transactions
        if (bidTxIds.length > 0) {
            const deletedTransactions = await wallet_trans_history_module.deleteMany({
                tx_request_number: { $in: bidTxIds }
            }).session(session);

            console.log(`🗑️ Deleted ${deletedTransactions.deletedCount} wallet transactions for ${bidTxIds.length} bid transactions`);

            if (deletedTransactions.deletedCount === 0) {
                console.log(`⚠️ No wallet transactions found for tx_request_numbers:`, bidTxIds);

                // Debug: Check what transactions exist for these users
                const userTransactions = await wallet_trans_history_module.find({
                    userDB_id: { $in: userIds },
                    amount_status: 5 // bid placed
                }).session(session);

                console.log(`🔍 Found ${userTransactions.length} bid transactions for users:`,
                    userTransactions.map(t => ({
                        userDB_id: t.userDB_id,
                        tx_request_number: t.tx_request_number,
                        amount: t.amount,
                        amount_status: t.amount_status
                    }))
                );
            }
        }

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

        // Prepare response
        const userRefundDetails = Object.keys(userSummary)
            .filter(userId => userSummary[userId].totalRefunded > 0)
            .map(userId => ({
                user_id: userId,
                user_name: userSummary[userId].user?.user_name || 'Unknown',
                refunded_amount: userSummary[userId].totalRefunded,
                new_balance: userSummary[userId].user?.wallet_balance || 0
            }));

        return res.status(200).json({
            success: true,
            message: `Successfully reverted ${revertedCount} bids. Total amount returned: ₹${totalRefunded.toFixed(2)}`,
            data: {
                revertedCount,
                totalRefunded,
                userRefundDetails,
                deletedBids: deleteResult.deletedCount
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertGalidisswarMultipleBids", error);
        return res.status(500).json({
            success: false,
            message: "Failed to revert bids: " + error.message
        });
    }
};




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",
            "digits",
            "points",
            "winning_points",
            "pana",
            "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 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 = "",
            start_date,
            end_date,
            selected_gameDB_id,
            selected_gameType,
            min_amount,
            userDB_id // ADD THIS: User filter parameter
        } = req.body;

        const fields = [
            "id",
            "user_name",
            "game_name",
            "pana",
            "session",
            "digits",
            "points",
            "bid_tx_id",
            "insert_date",
        ];
        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("orderField", orderField)

        // console.log("req.body in getBidHistoryData", req.body); // Check if userDB_id is received

        if (!start_date || !end_date) {
            return res.status(200).json({ success: false, msg: "Starting and ending dates 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);

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

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

        // ADD USER FILTERING
        if (userDB_id && mongoose.isValidObjectId(userDB_id)) {
            matchFilter.userDB_id = new mongoose.Types.ObjectId(userDB_id);
            console.log("🔍 Filtering by user:", userDB_id);
        }

        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,
                    insert_date: 1,
                    userDB_id: "$userData._id",
                    user_name: "$userData.user_name",
                    mobile: "$userData.mobile" // ADD MOBILE IF NEEDED
                }
            },
        ];

        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("pipelineWithPagination", pipelineWithPagination)

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

        // console.log("basePipeline in getBidHistoryData", JSON.stringify(pipelineWithPagination, null, 2));

        const [results, resultsIds, totalCountArr] = await Promise.all([
            bid_history_module.aggregate(pipelineWithPagination),
            bid_history_module.aggregate(basePipeline),
            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) => {
            console.log("🚀 ~ getBidHistoryData ~ v:", 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,
                insert_date: v.insert_date,
                user_name: v.user_name,
                userDB_id: v.userDB_id, // Make sure this is included
                mobile: v.mobile || "N/A" // Include mobile if available
            };

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

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

                case 'Full Sangam':
                    return {
                        ...common,
                        digit: `${v.digits}-${v.closedigits}`,
                        // 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':
                    const digit = sumDigits_with_reminder(String(v.digits));
                    return {
                        ...common,
                        digit: `${v.digits}-${v.closedigits}`,
                        // 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,
                        digit: v?.digits,
                        // 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,
                        digit: 'N/A',
                        // open_digit: 'N/A',
                        // close_digit: 'N/A',
                        // open_pana: 'N/A',
                        // close_pana: 'N/A',
                    };
            }
        });


        const all_ids = resultsIds.map(v => v._id);

        // console.log(`✅ Found ${data.length} records for user filtering`);

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

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


const getBidArchiveHistoryData = async (req, res) => {
    try {
        const {
            length = 100,
            start = 1,
            fieldIndex = 0,
            order = -1,
            searchValue = "",
            start_date,
            end_date,
            selected_gameDB_id,
            selected_gameType,
            min_amount,
            userDB_id // ADD THIS: User filter parameter
        } = 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); // Check if userDB_id is received

        if (!start_date || !end_date) {
            return res.status(200).json({ success: false, msg: "Starting and ending dates 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);

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

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

        // ADD USER FILTERING
        if (userDB_id && mongoose.isValidObjectId(userDB_id)) {
            matchFilter.userDB_id = new mongoose.Types.ObjectId(userDB_id);
            console.log("🔍 Filtering by user:", userDB_id);
        }

        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",
                    mobile: "$userData.mobile" // ADD MOBILE IF NEEDED
                }
            },
        ];

        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", JSON.stringify(pipelineWithPagination, null, 2));

        const [results, totalCountArr] = await Promise.all([
            bid_archive_history_module.aggregate(pipelineWithPagination),
            bid_archive_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,
                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,
                userDB_id: v.userDB_id, // Make sure this is included
                mobile: v.mobile || "N/A" // Include mobile if available
            };

            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(`✅ Found ${data.length} records for user filtering`);

        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 });
    }
};


// move bids to archive collection

let isArchiveRunning = false;

/**
 * Move 1-month-old bids to archive collection
 */


const archiveOldBids = async () => {
    if (isArchiveRunning) {
        console.log('Archive job is already running, skipping...');
        return { success: false, message: 'Archive job is already running' };
    }

    isArchiveRunning = true;
    const session = await mongoose.startSession();

    try {
        console.log('🔄 Starting bid archive process...');



        /**
         * Get archive days from fix_values configuration
         */
        const getArchiveDays = async () => {
            try {
                const fixValues = await fix_values_module.findOne({ app_id: 1 });
                return fixValues?.archive_history_days || 30; // Default to 30 days if not set
            } catch (error) {
                console.error('❌ Error getting archive days:', error);
                return 30; // Default fallback
            }
        };




        // Get archive days from configuration
        const archiveDays = await getArchiveDays();
        console.log("🚀 ~ archiveOldBids ~ archiveDays:", archiveDays)

        // Calculate date based on configured days
        const cutoffDate = new Date();
        cutoffDate.setDate(cutoffDate.getDate() - archiveDays);

        // Convert to UTC to avoid timezone issues
        const cutoffUTC = new Date(Date.UTC(
            cutoffDate.getUTCFullYear(),
            cutoffDate.getUTCMonth(),
            cutoffDate.getUTCDate(),
            cutoffDate.getUTCHours(),
            cutoffDate.getUTCMinutes(),
            cutoffDate.getUTCSeconds()
        ));

        console.log(`📅 Archiving bids older than: ${cutoffUTC.toISOString()} (${archiveDays} days)`);

        // Find bids older than configured days
        const oldBids = await bid_history_module.find({
            bid_date: { $lte: cutoffUTC.toISOString() }
        }).session(session);

        console.log(`📊 Found ${oldBids.length} bids to archive`);

        if (oldBids.length === 0) {
            console.log('✅ No old bids found to archive');
            return {
                success: true,
                message: 'No bids to archive',
                archivedCount: 0,
                archiveDays: archiveDays
            };
        }

        let result;
        await session.withTransaction(async () => {
            // Convert to plain objects and prepare for archive
            const archiveData = oldBids.map(bid => {
                const bidObj = bid.toObject();
                delete bidObj._id;
                return bidObj;
            });

            // Insert into archive collection
            await bid_archive_history_module.insertMany(archiveData, { session });

            // Delete from original collection
            await bid_history_module.deleteMany({
                _id: { $in: oldBids.map(bid => bid._id) }
            }).session(session);

            result = {
                success: true,
                message: `Successfully archived ${oldBids.length} bids`,
                archivedCount: oldBids.length,
                archiveDays: archiveDays
            };

            console.log(`✅ Archive completed: ${oldBids.length} bids moved to archive collection (${archiveDays} days threshold)`);
        });

        return result;

    } catch (error) {
        console.error('❌ Error in bid archive process:', error);
        return {
            success: false,
            message: 'Archive process failed',
            error: error.message
        };
    } finally {
        await session.endSession();
        isArchiveRunning = false;
    }
};





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",
            "ID",
            "user_name",
            "mobile",
            "amount",
            "remark",
            "insert_date",
            "fund_payment_receipt",
            "withdraw_type",
            "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',
                    mobile: '$user.mobile',
                    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" } } },
        //             ]
        //         }
        //     });
        // }
        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' } },

                        // Remove 'options: "i"' since searchRegex already contains the 'i' flag
                        { $expr: { $regexMatch: { input: { $toString: "$amount" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$mobile" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$fund_status" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$payment_method" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$withdraw_type" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$ac_number" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$paytm_number" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$google_pay_number" }, regex: searchRegex } } },
                        { $expr: { $regexMatch: { input: { $toString: "$phone_pay_number" }, regex: searchRegex } } },
                    ]
                }
            });
        }




        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 } } },
                // {$match : baseMatch},
                { $group: { _id: "$fund_status", total: { $sum: "$amount" } } }
            ])
        ]);

        const totalFiltered = countResult?.[0]?.total || 0;
        const totalWithdrawAmt = withdrawAmountData[0]?.total || 0;
        console.log(startDate, endDate, "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." });
    }
};


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 = [
            "ID",
            "mobile",
            "user_name",
            "before_wallet",
            "amount",
            "affter_wallet",
            "remark",
            "insert_date",
            "reject_remark",
            "fund_payment_receipt",
            "deposit_type",
            "fund_status",
        ];

        // console.log("body-", req.body)

        const {
            length = 10,
            start = 1,
            fieldIndex = 0,
            searchValue = "",
            deposit_date = "",
            start_deposit_date,
            end_deposit_date,
            type = 0,

        } = 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 },
            transaction_type: { $eq: 1 }
        };
        if (type) {
            baseMatch.amount_status = { $eq: type }
        }
        // console.log("basepipeline for aggrement")
        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",
                    before_wallet: 1,
                    amount: 1,
                    tx_request_number: 1,
                    transaction_note: 1,
                    amount_status: 1,
                    // reject_remark: 1,
                    // deposit_type: 1,
                    // payment_method: 1,
                    // txn_ref: 1,
                    // fund_status: 1,
                    // deposit_type: 1,
                    // fund_payment_receipt: 1,
                    // isAction: {
                    //     $cond: [
                    //         { $ne: ['$fund_status', 0] },
                    //         0,
                    //         1
                    //     ]
                    // }

                    insert_date: 1,
                }
            },
        ];

        if (searchValue) {
            basePipeline.push({
                $match: {
                    $or: [
                        { user_name: { $regex: searchValue, $options: 'i' } },
                        { transaction_note: { $regex: searchValue, $options: 'i' } },
                        { $expr: { $regexMatch: { input: { $toString: "$amount" }, regex: searchValue } } },
                        { $expr: { $regexMatch: { input: { $toString: "$mobile" }, regex: searchValue } } },
                        { $expr: { $regexMatch: { input: { $toString: "$before_wallet" }, regex: searchValue } } },
                        // { user_name: { $regex: `^${searchValue}`, $options: 'i' } },
                        // { transaction_note: { $regex: `^${searchValue}`, $options: 'i' } },
                        // { $expr: { $regexMatch: { input: { $toString: "$amount" }, regex: searchRegex, options: "i" } } },
                        // { $expr: { $regexMatch: { input: { $toString: "$mobile" }, regex: searchRegex, options: "i" } } },
                        // { $expr: { $regexMatch: { input: { $toString: "$before_wallet" }, regex: searchRegex, options: "i" } } },
                        // { tx_request_number: { $regex: `^${searchValue}`, $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, totalpgData, totalAdminData, totalUserData] = await Promise.all([
            wallet_trans_history_module.aggregate(pipelineWithPagination),
            wallet_trans_history_module.aggregate([...basePipeline, { $count: "total" }]),
            wallet_trans_history_module.aggregate([
                {
                    $match: {
                        insert_date: { $gte: startDate, $lte: endDate },
                        transaction_type: { $eq: 1 },
                        amount_status: { $eq: 99 },
                    }
                },
                { $group: { _id: null, total: { $sum: "$amount" } } }
            ]),
            wallet_trans_history_module.aggregate([
                {
                    $match: {
                        insert_date: { $gte: startDate, $lte: endDate },
                        transaction_type: { $eq: 1 },
                        amount_status: { $eq: 1 }
                    }
                },
                { $group: { _id: null, total: { $sum: "$amount" } } }
            ]),
            wallet_trans_history_module.aggregate([
                {
                    $match: {
                        insert_date: { $gte: startDate, $lte: endDate },
                        transaction_type: { $eq: 1 },
                        amount_status: { $eq: 19 }
                    }
                },
                { $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
        }));

        // console.log("🚀 ~ getAutoDepositeHistory ~ totalpgData[0]?.total:", totalpgData[0]?.total)
        // console.log("🚀 ~ getAutoDepositeHistory ~ totalAdminData[0]:", totalAdminData[0])
        // console.log("🚀 ~ getAutoDepositeHistory ~ totalUserData[0]:", totalUserData[0])

        // Fixed calculation with explicit parentheses to ensure all terms are evaluated and added
        const deposit_amt = (totalUserData[0]?.total || 0) + (totalAdminData[0]?.total || 0) + (totalpgData[0]?.total || 0);
        // console.log("🚀 ~ getAutoDepositeHistory ~ deposit_amt:", deposit_amt)

        return res.json({
            success: true,
            recordsFiltered: totalFiltered,
            total_admin_deposit: totalAdminData[0]?.total || 0,
            total_user_deposit: totalUserData[0]?.total || 0,
            deposit_amt,
            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;

        if (!result_dec_date || !gameDB_id) {
            return res.status(400).json({ success: false, msg: "Result date and game Id not found !" });
        }

        const gameData = await games_module.findById(gameDB_id);
        let gameName = '';

        if (!gameData) {
            return res.status(400).json({ success: false, msg: "Game data not found !" });
        } else {
            gameName = gameData.game_name;
        }

        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" });
        }
        if (!result?.open_number) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, message: "Save open no. before declare result!" });
        }

        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);

        // check admin wallet amount is sufficenet or not to distribute in all winning users

        let TotalBidWinAmt = 0;
        for (const bid of result_bid) {
            const { pana, points, digits } = bid;

            switch (pana) {
                case 'Single Digit':
                    if (win_digit == digits) {
                        TotalBidWinAmt += (single_digit_val_2 / single_digit_val_1) * points;

                    }
                    break;
                case 'Triple Pana':
                    if (open_number === digits) {
                        TotalBidWinAmt += (tripple_pana_val_2 / tripple_pana_val_1) * points;
                    }
                    break;
                case 'Double Pana':
                    if (open_number === digits) {
                        TotalBidWinAmt += (double_pana_val_2 / double_pana_val_1) * points;
                    }
                    break;
                case 'Single Pana':
                    if (open_number === digits) {
                        TotalBidWinAmt += (single_pana_val_2 / single_pana_val_1) * points;
                    }
                    break;
            }
        }

        let admin_id;

        if (req?.admin?._id) {
            admin_id = req?.admin?._id;
        }

        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 }
                    ),
                    admin_module.findByIdAndUpdate(
                        admin_id,
                        { $inc: { wallet_amount: -win_amt } },
                        { new: true, session }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        main_gameDB_id: gameDB_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 });
        }

        // call or send the firebase live notification when result declare for starline game
        const SLMsg = await sendFBNotification(
            `${gameName} `,
            `${open_number}-${win_digit} `,
            '',
            {} // no res → internal call
        );



        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;

        if (!result_dec_date || !gameDB_id) {
            return res.status(400).json({ success: false, msg: "Result date and game Id not found !" });
        }

        const gameData = await games_module.findById(gameDB_id);
        let gameName = '';

        if (!gameData) {
            return res.status(400).json({ success: false, msg: "Game data not found !" });
        } else {
            gameName = gameData.game_name;
        }



        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 || !result.close_number || result.close_number == 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(200).json({ success: false, msg: "Please declare the open result and save close result before declaring" });
        }

        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;
        console.log("🚀 ~ decleareCloseData ~ win_open_digit:", win_open_digit)
        const win_close_digit = close_number?.split('').reduce((a, b) => a + Number(b), 0) % 10;
        console.log("🚀 ~ decleareCloseData ~ win_close_digit:", win_close_digit)

        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);
        console.log("🚀 ~ decleareCloseData ~ result_bid:", result_bid)


        let admin_id;
        if (req?.admin?._id) {
            admin_id = req?.admin?._id;
        }
        else {
            console.log("admin id not found for update the admin wallet amount for winning user !")
            return res.status(400).json({ success: false, msg: "Admin id not found for update wallet amount!" })
        }



        let totalBidWinAmt = 0;
        console.log("resultbid", result_bid)
        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':
                    console.log(`methcing done${win_close_digit} -----${digits}------ ${win_close_digit == digits} ---++++++${close_number}++++++${closedigits}++++++++++ ${close_number === closedigits}`)

                    if (win_close_digit == digits && close_number == closedigits) {
                        console.log("methcing done-------HS-A")
                        win_amt = (half_sangam_val_2 / half_sangam_val_1) * points;
                        matched = true;
                        break;
                    }

                    console.log(`methcing done${close_number} -----${digits}------ ${close_number == digits} ---++++++${win_close_digit}++++++${closedigits}++++++++++ ${win_close_digit == closedigits}`)
                    if (close_number == digits && win_close_digit == closedigits) {
                        console.log("methcing done-------HS-B")
                        win_amt = (half_sangam_val_2 / half_sangam_val_1) * points;
                        matched = true;
                        break;
                    }
                    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':
                    console.log("🚀 ~ decleareCloseData ~ win_open_digit, win_close_digit:", win_open_digit, win_close_digit)
                    const jodiSum1 = `${win_open_digit}${win_close_digit}`;

                    console.log("🚀 ~ decleareCloseData ~ jodiSum1:", jodiSum1)
                    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) {
                totalBidWinAmt += win_amt;
            }
        }


        if (req?.admin?.wallet_amount < totalBidWinAmt) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({ success: false, msg: "Admin wallet amount is insufficient to declare close result!" });
        }


        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':
                    console.log(`methcing done${win_close_digit} -----${digits}------ ${win_close_digit == digits} ---++++++${close_number}++++++${closedigits}++++++++++ ${close_number === closedigits}`)

                    if (win_close_digit == digits && close_number == closedigits) {
                        console.log("methcing done-------HS-A")
                        win_amt = (half_sangam_val_2 / half_sangam_val_1) * points;
                        matched = true;
                        break;
                    }

                    console.log(`methcing done${close_number} -----${digits}------ ${close_number == digits} ---++++++${win_close_digit}++++++${closedigits}++++++++++ ${win_close_digit == closedigits}`)
                    if (close_number == digits && win_close_digit == closedigits) {
                        console.log("methcing done-------HS-B")
                        win_amt = (half_sangam_val_2 / half_sangam_val_1) * points;
                        matched = true;
                        break;
                    }
                    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}`;
                    console.log("🚀 ~ decleareCloseData ~ jodiSum1:", jodiSum1)
                    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,
                        main_gameDB_id: gameDB_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 }),
                    admin_module.findByIdAndUpdate(admin_id, {
                        $inc: { wallet_amount: -win_amt }
                    }),
                    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 });
        }

        // call or send the firebase live notification when result declare for starline game
        const SLMsg = await sendFBNotification(
            `${gameName}`,
            `${open_number}-${win_open_digit}${win_close_digit}-${close_number}`,
            '',
            {} // no res → internal call
        );



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



        return res.status(200).json({
            success: true,
            message: "Close result declared successfully",
            is_close_declare: true,
            SLMsg

        });

    } 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;
                    console.log("🚀 ~ getOpenWinnerList ~ win_number:", win_number)
                    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) {

                    console.log("pana matched with Triple pana");
                    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) {

                    console.log("pana matched with Double pana");
                    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,
                        Number: item?.digits,
                        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;
            console.log("🚀 ~ getCloseWinnerList ~ open_number:", open_number)
            const close_number = item?.close_number;
            console.log("🚀 ~ getCloseWinnerList ~ close_number:", 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;
            // console.log("🚀 ~ getCloseWinnerList ~ game_rate:", 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;
            let bid_number = ''

            for (const bid of bid_data) {
                console.log("bid id", bid._id)
                let win_amount = 0;

                const bidPoints = bid.points;

                switch (bid.pana) {
                    case 'Single Digit':
                        console.log("first 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;
                        bid_number = digitSum
                        break;

                    case 'Half Sangam':
                        console.log("first Half Sangam")
                        const closeDigitSum = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        console.log("🚀 ~ getCloseWinnerList ~ closeDigitSum:", closeDigitSum)
                        // if half sangam type A (mean bid digit is a digit value and bid close digit value is pana no.)
                        if (closeDigitSum == bid.digits && close_number == bid.closedigits) {

                            console.log("Half Sangam enter")
                            win_amount = (half_sangam_val_2 / half_sangam_val_1) * bidPoints;

                            bid_number = `${close_number}-${closeDigitSum}`

                        }

                        // if half sangam type A (mean bid digit is a pana value and bid close digit value is digit.)
                        if (close_number == bid.digits && closeDigitSum == bid.closedigits) {

                            console.log("Half Sangam enter")
                            win_amount = (half_sangam_val_2 / half_sangam_val_1) * bidPoints;
                            bid_number = `${closeDigitSum}-${close_number}`
                        }

                        break;

                    case 'Full Sangam':
                        console.log("first Full Sangam")
                        if (open_number == bid.digits && close_number == bid.closedigits) {

                            win_amount = (full_sangam_val_2 / full_sangam_val_1) * bidPoints;
                            bid_number = `${open_number}-${close_number}`
                        }
                        break;

                    // case 'TP':
                    case 'Triple Pana':
                        console.log("first Triple Pana")
                        if (close_number == bid.digits) {

                            win_amount = (tripple_pana_val_2 / tripple_pana_val_1) * bidPoints;
                            bid_number = close_number
                        }
                        break;

                    // case 'DP':
                    case 'Double Pana':
                        console.log("first Double Pana")
                        if (close_number == bid.digits) {
                            win_amount = (double_pana_val_2 / double_pana_val_1) * bidPoints;
                            bid_number = close_number
                        }
                        break;

                    case 'Single Pana':
                        // case 'SP':
                        if (close_number == bid.digits) {

                            win_amount = (single_pana_val_2 / single_pana_val_1) * bidPoints;
                            bid_number = close_number
                        }
                        break;

                    case 'Jodi Digit':
                        console.log("first Jodi Digit")
                        const closeDigit_jodi = close_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        console.log("🚀 ~ getCloseWinnerList ~ closeDigit_jodi:", closeDigit_jodi)
                        const openDigit_jodi = open_number.split('').reduce((a, b) => +a + +b, 0) % 10;
                        console.log("🚀 ~ getCloseWinnerList ~ openDigit_jodi:", openDigit_jodi)

                        const jodi_jodi = `${openDigit_jodi}${closeDigit_jodi}`;
                        if (jodi_jodi == bid.digits) {

                            console.log("🚀 ~ getCloseWinnerList ~ jodi_jodi == bid.digits:", jodi_jodi == bid.digits)

                            win_amount = (jodi_digit_val_2 / jodi_digit_val_1) * bidPoints;
                            bid_number = jodi_jodi
                        }
                        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;
                        bid_number = red_bracket
                        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;
                        bid_number = group_jodi
                        break;
                }

                if (win_amount > 0) {
                    data_array.push({
                        points: bidPoints,
                        userDB_id: bid.userDB_id,
                        user_name: bid.user_name,
                        pana: bid.pana,
                        Number: bid_number,
                        bid_tx_id: bid.bid_tx_id,
                        win_amt: win_amount
                    });
                    win_amt_sum += win_amount;
                    points_amt_sum += bidPoints;
                }
            }

            console.log("data_array before sangam", data_array)

            // Handle Close session "Half Sangam" and "Full 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: "Close",
            //             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
            //         }
            //     }
            // ]);
            // console.log("🚀 ~ getCloseWinnerList ~ result_2:", result_2)

            // for (const bid of result_2) {
            //     console.log("result 2 open_number", open_number)
            //     const openDigit = open_number.split('').reduce((a, b) => +a + +b, 0) % 10;
            //     console.log("🚀 ~ getCloseWinnerList ~ openDigit:", openDigit)
            //     if (close_number == bid.closedigits && openDigit == bid.digits) {
            //         const win_amt = (half_sangam_val_2 / half_sangam_val_1) * 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;
            //     }
            // }

            // console.log("data_array after half sangam", data_array)



            // Handle Close session "Half Sangam" and "Full sangam" entries separately
            // const result_3 = await bid_history_module.aggregate([
            //     {
            //         $match: {
            //             gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            //             pay_status: 0,
            //             bid_date: { $gte: startDate, $lte: endDate },
            //             session: "Close",
            //             pana: "Full 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
            //         }
            //     }
            // ]);
            // console.log("🚀 ~ getCloseWinnerList ~ result_3:", result_3)


            // for (const bid of result_3) {

            //     console.log("result 3 open_number", open_number)

            //     if (close_number == bid.closedigits && open_number == bid.digits) {
            //         const win_amt = (full_sangam_val_2 / full_sangam_val_1) * bid.points;
            //         data_array.push({
            //             points: bid.points,
            //             userDB_id: bid.userDB_id,
            //             user_name: bid.user_name,
            //             pana: "Full Sangam",
            //             bid_tx_id: bid.bid_tx_id,
            //             win_amt
            //         });
            //         win_amt_sum += win_amt;
            //         points_amt_sum += bid.points;
            //     }
            // }

            console.log("data_array after sangam", data_array)

            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,
            startDate,  // Changed from predictionDate
            endDate,    // Added endDate
            gameDB_id = "",
            gameType = ""
        } = req.body;

        const fields = [
            "points",
            "winning_points",
            "bid_date"
        ];

        const limit = parseInt(length);
        const page = parseInt(start);
        const skip = !searchValue && page !== 0 ? (page - 1) : 0;


        // const orderField = fields[fieldIndex] || "insert_date";
        let orderField = "insert_date";

        switch (fieldIndex) {
            case 8:
                orderField = fields[0];
                break;
            case 9:
                orderField = fields[1];
                break;
            case 11:
                orderField = "insert_date";
                break;
            default:
                orderField = "insert_date";
                break;
        }

        const orderDir = parseInt(order);
        const searchTerm = searchValue.trim();

        // Validate dates
        if (!startDate || !endDate) {
            return res.status(400).json({
                success: false,
                message: "Start date and end date are required"
            });
        }

        // Convert dates to IST and create proper date range
        const istStartDate = moment_timeZone.tz(startDate, "Asia/Kolkata").startOf("day").toDate();
        const istEndDate = moment_timeZone.tz(endDate, "Asia/Kolkata").endOf("day").toDate();

        console.log("🚀 ~ getStarlineBidHistoryData ~ istStartDate:", istStartDate);
        console.log("🚀 ~ getStarlineBidHistoryData ~ istEndDate:", istEndDate);

        const matchFilter = {
            pay_status: 0,
            bid_date: {
                $gte: istStartDate,
                $lte: istEndDate
            },
        };

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


        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,
                    winning_points: 1,
                    pana: 1,
                    game_name: 1,
                    bid_tx_id: 1,
                    digits: 1,
                    insert_date: 1,
                    user_name: "$userData.user_name",
                    mobile_number: "$userData.mobile"
                }
            },
        ];

        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" }]),
        ]);


        console.log("🚀 ~ getStarlineBidHistoryData ~ results:", results)
        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,
                winning_points: v.winning_points,
                game_type: v.pana,
                game_name: v.game_name,
                bid_tx_id: v.bid_tx_id,
                user_name: v.user_name,
                mobile_number: v.mobile_number,
                insert_date: v.insert_date
            };

            switch (v.pana) {
                case 'Single Digit':
                    return {
                        ...common,
                        pana: 'N/A',
                        digit: v.digits,
                    };
                case 'Single Pana':
                    return {
                        ...common,
                        pana: 'N/A',
                        digit: v.digits,
                    };
                case 'Double Pana':
                    return {
                        ...common,
                        pana: 'N/A',
                        digit: v.digits,
                    };
                case 'Triple Pana':
                    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;
        console.log("🚀 ~ getStarlineWinnerList ~ req.body:", req.body)

        const fields = [
            "user_name",
            "digits",
            "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((a, b) => a + parseInt(b, 10), 0);

        // last digit after sum
        const lastDigit = sumDigits(selected_number) % 10;

        console.log("selected_number:", selected_number);
        console.log("lastDigit for Single Digit:", lastDigit);

        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_sum_digit] }
            //                 },
            //                 {
            //                     case: {
            //                         $in: [
            //                             "$pana",
            //                             ["Single Pana", "Double Pana", "Triple Pana"]
            //                         ]
            //                     },
            //                     then: {
            //                         $eq: [{ $toInt: "$digits" }, selected_number]
            //                     }
            //                 }
            //             ],
            //             default: false
            //         }
            //     }
            // }
            $match: {
                $expr: {
                    $switch: {
                        branches: [
                            {
                                case: { $eq: ["$pana", "Single Digit"] },
                                then: { $eq: [{ $toInt: "$digits" }, lastDigit] } // match 5
                            },
                            {
                                case: { $in: ["$pana", ["Single Pana", "Double Pana", "Triple Pana"]] },
                                then: { $eq: ["$digits", selected_number] } // match full number like "456"
                            }
                        ],
                        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, totalBidAmt] = 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" }
                    }
                }
            ]),
            starline_bid_history_module.aggregate([
                { $match: matchFilter },
                {
                    $group: {
                        _id: null,
                        total_bid_amount: { $sum: "$points" }
                    }
                }
            ])
        ]);
        // console.log("🚀 ~ getStarlineWinnerList ~ totalBidAmt:", totalBidAmt)

        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 = totalBidAmt[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 });
    }
};


//star line result history list data
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
            ? {
                $and: [
                    { result_date: { $gte: startDate, $lte: endDate } },
                    { open_decleare_date: { $exists: true, $ne: null } }
                ]
            }
            : { open_decleare_date: { $exists: true, $ne: null } };

        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: {
                                $dateFromParts: {
                                    year: { $year: { date: "$result_date", timezone: "Asia/Kolkata" } },
                                    month: { $month: { date: "$result_date", timezone: "Asia/Kolkata" } },
                                    day: { $dayOfMonth: { date: "$result_date", timezone: "Asia/Kolkata" } }
                                }
                            },
                            timezone: "Asia/Kolkata"
                        }
                    },
                    open_decleare_date: 1, // Keep the original date field
                    open_decleare_date_f: {
                        $cond: {
                            if: { $ne: ['$open_decleare_date', null] }, // Check if not null
                            then: { $dateToString: { format: '%d %b %Y %H:%M:%S', date: '$open_decleare_date' } },
                            else: 'N/A'
                        }
                    },
                    game_name: '$game.game_name',
                    open_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_f || 'N/A'; // Use the formatted date

            // If formatted date is 'N/A' but we have the original date, format it
            if (open_date === 'N/A' && rs.open_decleare_date) {
                open_date = moment_timeZone(rs.open_decleare_date).format('DD MMM YYYY HH:mm:ss');
            }

            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,
                _id: rs._id // Include the _id for delete/revert operations
            };
        });

        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' });
    }
};

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

    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 < 0) {
            await session.abortTransaction();
            session.endSession();
            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();

        // Generate unique result token for this result
        const open_result_token = getUserRandomToken();

        // Prepare insert and query objects
        const insertData = {
            gameDB_id,
            result_date: istDate,
            open_number: pana_number,
            open_result_token: open_result_token, // Add the token
            open_decleare_status: 0, // Set to 0 (saved but not declared)
        };

        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).session(session);

        if (existing) {
            // Update existing record with new result and token
            existing.open_number = pana_number;
            existing.open_result_token = open_result_token;
            existing.open_decleare_status = 0;
            await existing.save({ session });
        } else {
            // Create new record
            await starline_game_result_history_module.create([insertData], { session });
        }

        // Calculate winners and update bid records (but don't pay yet)
        const bidWhere = {
            gameDB_id: gameDB_id,
            bid_date: { $gte: startDate, $lte: endDate },
            pay_status: 0 // Only process pending bids
        };

        // Find all bids for this game and date
        const allBids = await starline_bid_history_module.find(bidWhere).session(session);

        let totalWinningAmount = 0;
        let winningBidsCount = 0;

        // Process each bid to check if it's a winner
        for (const bid of allBids) {
            let isWinner = false;
            let winMultiplier = 0;

            // Check different pana types and calculate winning points
            if (bid.pana === pana_number) {
                // Exact pana match - check pana type and apply multiplier
                const panaType = utils_handler.getPanaType(pana_number);

                switch (panaType) {
                    case 'single':
                        winMultiplier = 10; // Adjust based on your game rates
                        break;
                    case 'double':
                        winMultiplier = 15; // Adjust based on your game rates
                        break;
                    case 'triple':
                        winMultiplier = 25; // Adjust based on your game rates
                        break;
                    default:
                        winMultiplier = 10;
                }
                isWinner = true;
            } else if (bid.digits === auto_digit) {
                // Digit match
                winMultiplier = 9; // Standard digit multiplier
                isWinner = true;
            }

            if (isWinner) {
                const winningPoints = bid.points * winMultiplier;

                // Update bid with winning information but don't mark as paid yet
                await starline_bid_history_module.updateOne(
                    { _id: bid._id },
                    {
                        $set: {
                            open_result_token: open_result_token,
                            winning_points: winningPoints,
                            status: 1, // Mark as won but not paid
                            // pay_status remains 0 (not paid until declared)
                        }
                    },
                    { session }
                );

                totalWinningAmount += winningPoints;
                winningBidsCount++;
            }
        }

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



        // Simple success response like main game
        return res.json({
            success: true

        });

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

// Add this utility function
const utils_handler = {
    getPanaType: (pana) => {
        const digits = pana.split('').map(Number);
        const uniqueDigits = [...new Set(digits)];

        if (uniqueDigits.length === 1) return 'triple';
        if (uniqueDigits.length === 2) return 'double';
        return 'single';
    }
};



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

//     try {
//         const {
//             gameDB_id,
//             result_dec_date,
//             resultId
//         } = req.body;

//         console.log("🚀 ~ completeStarlineBidRevert ~ req.body:", req.body);

//         if (!gameDB_id || !result_dec_date || !resultId) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({
//                 success: false,
//                 message: "Missing required fields: gameDB_id, result_dec_date, resultId"
//             });
//         }

//         // Convert date to proper format
//         const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
//         const startDate = istDate.clone().startOf("day").toDate();
//         const endDate = istDate.clone().endOf("day").toDate();

//         console.log(`🔍 Searching for result: ${resultId}`);

//         // Step 1: Find the result document
//         const result = await starline_game_result_history_module.findOne({
//             _id: resultId,
//             gameDB_id: gameDB_id,
//             result_date: { $gte: startDate, $lte: endDate }
//         }).session(session);

//         if (!result) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({
//                 success: false,
//                 message: "Result not found"
//             });
//         }

//         console.log(`✅ Found result: ${result.open_number}, token: ${result.open_result_token}`);

//         const open_result_token = result.open_result_token;

//         // Step 2: Find all bids for this result
//         const allBids = await starline_bid_history_module.find({
//             gameDB_id: gameDB_id,
//             bid_date: { $gte: startDate, $lte: endDate }
//         }).session(session);

//         console.log(`📊 Found ${allBids.length} bids to process`);

//         let totalWinningRefunded = 0;
//         let totalBetAmountRefunded = 0;
//         let processedBidsCount = 0;

//         // Step 3: First, find and process existing wallet transactions to deduct winnings
//         console.log(`🔍 Searching for existing wallet transactions with token: ${open_result_token}`);
//         const existingWalletTransactions = await wallet_trans_history_module.find({
//             open_result_token: open_result_token,
//             transaction_type: 1, // Credit transactions (winning amounts)
//             amount_status: 8 // Winning amount status
//         }).session(session);

//         console.log(`📊 Found ${existingWalletTransactions.length} existing winning transactions`);

//         // Process existing winning transactions to deduct from users and add to admin
//         for (const walletTx of existingWalletTransactions) {
//             try {
//                 const userDB_id = walletTx.userDB_id;
//                 const betAmount = walletTx.amount;
//                 const bid_tx_id = walletTx.bid_tx_id;

//                 console.log(`💸 Processing winning deduction for user ${userDB_id}, amount: ${winningAmount}`);

//                 // Get user current balance
//                 const user = await user_module.findById(userDB_id).session(session);
//                 if (!user) {
//                     console.log(`⚠️ User ${userDB_id} not found, skipping wallet transaction`);
//                     continue;
//                 }

//                 const userBeforeBalance = user.wallet_balance;

//                 // Only process if user has sufficient balance
//                 if (userBeforeBalance >= betAmount) {
//                     // Deduct winning amount from user
//                     await user_module.findByIdAndUpdate(
//                         userDB_id,
//                         { $inc: { wallet_balance: betAmount } },
//                         { session }
//                     );

//                     await admin_module.findByIdAndUpdate(req?.admin?._id, { $inc: { wallet_amount: -betAmount } });

//                     // Add winning amount to admin
//                     const adminUserId = '68ddfc4b5b2b66e1d148ea86'; // Replace with actual admin ID
//                     const adminUser = await user_module.findById(adminUserId).session(session);
//                     const adminBeforeBalance = adminUser.wallet_balance;

//                     await user_module.findByIdAndUpdate(
//                         adminUserId,
//                         { $inc: { wallet_balance: betAmount } },
//                         { session }
//                     );

//                     // Create transaction record for winning amount deduction from user
//                     const refundTxToken = getUserRandomToken();
//                     await new wallet_trans_history_module({
//                         userDB_id: userDB_id,
//                         amount: winningAmount,
//                         transaction_type: 2, // Debit
//                         amount_status: 11, // Bid revert - winning amount deducted
//                         transaction_note: `Bid revert - winning amount deducted`,
//                         tx_request_number: refundTxToken + '_win_deduct',
//                         bid_tx_id: bid_tx_id,
//                         open_result_token: open_result_token,
//                         before_wallet: userBeforeBalance,
//                         after_wallet: userBeforeBalance - winningAmount
//                     }).save({ session });

//                     // Create transaction record for winning amount addition to admin
//                     await new wallet_trans_history_module({
//                         userDB_id: adminUserId,
//                         amount: winningAmount,
//                         transaction_type: 1, // Credit
//                         amount_status: 12, // Bid revert - winning amount credited to admin
//                         transaction_note: `Bid revert - winning amount credited from user ${userDB_id}`,
//                         tx_request_number: refundTxToken + '_win_admin',
//                         bid_tx_id: bid_tx_id,
//                         open_result_token: open_result_token,
//                         before_wallet: adminBeforeBalance,
//                         after_wallet: adminBeforeBalance + winningAmount
//                     }).save({ session });

//                     totalWinningRefunded += winningAmount;
//                     console.log(`✅ Successfully deducted winning amount from user ${userDB_id}`);
//                 } else {
//                     console.log(`⚠️ User ${userDB_id} has insufficient balance: ${userBeforeBalance}, required: ${winningAmount}`);
//                 }

//             } catch (walletError) {
//                 console.error(`❌ Failed to process wallet transaction for user ${walletTx.userDB_id}:`, walletError);
//             }
//         }

//         // Step 4: Process each bid to refund bet amounts
//         for (const bid of allBids) {
//             try {
//                 const userDB_id = bid.userDB_id;
//                 const bidPoints = bid.points || 0;

//                 console.log(`💸 Processing bet refund for bid ${bid.bid_tx_id}: bet=${bidPoints}`);

//                 // Get user current balance (after winning deduction)
//                 const user = await user_module.findById(userDB_id).session(session);
//                 if (!user) {
//                     console.log(`⚠️ User ${userDB_id} not found, skipping bid`);
//                     continue;
//                 }

//                 const userBeforeBalance = user.wallet_balance;

//                 // REFUND: Refund bet amount (add to user, deduct from admin)
//                 if (bidPoints > 0) {
//                     // Add bet amount back to user
//                     await user_module.findByIdAndUpdate(
//                         userDB_id,
//                         { $inc: { wallet_balance: bidPoints } },
//                         { session }
//                     );

//                     // Deduct bet amount from admin
//                     const adminUserId = '68ddfc4b5b2b66e1d148ea86'; // Replace with actual admin ID
//                     const adminUser = await user_module.findById(adminUserId).session(session);
//                     const adminBeforeBalance = adminUser.wallet_balance;

//                     await user_module.findByIdAndUpdate(
//                         adminUserId,
//                         { $inc: { wallet_balance: -bidPoints } },
//                         { session }
//                     );

//                     // Create transaction record for bet amount addition to user
//                     const refundTxToken = getUserRandomToken();
//                     await new wallet_trans_history_module({
//                         userDB_id: userDB_id,
//                         amount: bidPoints,
//                         transaction_type: 1, // Credit
//                         amount_status: 13, // Bid revert - bet amount refunded
//                         transaction_note: `Bid revert - bet amount refunded`,
//                         tx_request_number: refundTxToken + '_bet_refund',
//                         bid_tx_id: bid.bid_tx_id,
//                         open_result_token: open_result_token,
//                         before_wallet: userBeforeBalance,
//                         after_wallet: userBeforeBalance + bidPoints
//                     }).save({ session });

//                     // Create transaction record for bet amount deduction from admin
//                     await new wallet_trans_history_module({
//                         userDB_id: adminUserId,
//                         amount: bidPoints,
//                         transaction_type: 2, // Debit
//                         amount_status: 14, // Bid revert - bet amount deducted from admin
//                         transaction_note: `Bid revert - bet amount deducted for user ${userDB_id}`,
//                         tx_request_number: refundTxToken + '_bet_admin',
//                         bid_tx_id: bid.bid_tx_id,
//                         open_result_token: open_result_token,
//                         before_wallet: adminBeforeBalance,
//                         after_wallet: adminBeforeBalance - bidPoints
//                     }).save({ session });

//                     totalBetAmountRefunded += bidPoints;
//                     console.log(`✅ Successfully refunded bet amount to user ${userDB_id}`);
//                 }

//                 processedBidsCount++;

//             } catch (bidError) {
//                 console.error(`❌ Failed to process bid ${bid.bid_tx_id}:`, bidError);
//                 // Continue with other bids
//             }
//         }

//         // Step 5: Delete OLD wallet transaction records (the original winning transactions)
//         const deletedOldWalletTransactions = await wallet_trans_history_module.deleteMany({
//             open_result_token: open_result_token,
//             transaction_type: 1, // Original credit transactions
//             amount_status: 8 // Original winning amount status
//         }).session(session);

//         console.log(`🗑️ Deleted ${deletedOldWalletTransactions.deletedCount} OLD wallet transaction records`);

//         // Step 6: Delete all bid documents for this game and date
//         const deletedBids = await starline_bid_history_module.deleteMany({
//             gameDB_id: gameDB_id,
//             bid_date: { $gte: startDate, $lte: endDate }
//         }).session(session);

//         console.log(`🗑️ Deleted ${deletedBids.deletedCount} bid documents`);

//         // Step 7: Delete user notifications
//         const deletedNotifications = await user_notification_module.deleteMany({
//             $or: [
//                 { open_result_token: open_result_token },
//                 { msg: { $regex: result.open_number, $options: 'i' } }
//             ]
//         }).session(session);

//         console.log(`🗑️ Deleted ${deletedNotifications.deletedCount} notification records`);

//         // Step 8: Finally delete the result history record
//         await starline_game_result_history_module.deleteOne({
//             _id: resultId
//         }).session(session);

//         console.log(`🗑️ Deleted result history record: ${resultId}`);

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

//         return res.status(200).json({
//             success: true,
//             message: "Complete bid revert successful",
//             data: {
//                 processedBidsCount: processedBidsCount,
//                 totalWinningRefunded: totalWinningRefunded,
//                 totalBetAmountRefunded: totalBetAmountRefunded,
//                 deletedBidsCount: deletedBids.deletedCount,
//                 deletedOldWalletTransactions: deletedOldWalletTransactions.deletedCount,
//                 deletedNotifications: deletedNotifications.deletedCount
//             }
//         });

//     } catch (error) {
//         await session.abortTransaction();
//         session.endSession();
//         console.error("❌ Error in completeStarlineBidRevert:", error);
//         return res.status(500).json({
//             success: false,
//             message: error.message
//         });
//     }
// };

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

//     try {
//         const {
//             gameDB_id,
//             result_dec_date,
//             resultId
//         } = req.body;

//         console.log("🚀 ~ completeStarlineBidRevert ~ req.body:", req.body);

//         if (!gameDB_id || !result_dec_date || !resultId) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(400).json({
//                 success: false,
//                 message: "Missing required fields: gameDB_id, result_dec_date, resultId"
//             });
//         }

//         // Convert date to proper format
//         const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
//         const startDate = istDate.clone().startOf("day").toDate();
//         const endDate = istDate.clone().endOf("day").toDate();

//         console.log(`🔍 Searching for result: ${resultId}`);

//         // Step 1: Find the result document
//         const result = await starline_game_result_history_module.findOne({
//             _id: resultId,
//             gameDB_id: gameDB_id,
//             result_date: { $gte: startDate, $lte: endDate }
//         }).session(session);

//         if (!result) {
//             await session.abortTransaction();
//             session.endSession();
//             return res.status(404).json({
//                 success: false,
//                 message: "Result not found"
//             });
//         }

//         console.log(`✅ Found result: ${result.open_number}, token: ${result.open_result_token}`);

//         const open_result_token = result.open_result_token;

//         // Step 2: Find all bids for this result
//         const allBids = await starline_bid_history_module.find({
//             gameDB_id: gameDB_id,
//             bid_date: { $gte: startDate, $lte: endDate }
//         }).session(session);

//         console.log(`📊 Found ${allBids.length} bids to process`);

//         let totalWinningRefunded = 0;
//         let totalBetAmountRefunded = 0;
//         let processedBidsCount = 0;

//         // Step 3: Process each bid for refunds
//         for (const bid of allBids) {
//             try {
//                 const userDB_id = bid.userDB_id;
//                 const bidPoints = bid.points || 0;
//                 const winningPoints = bid.winning_points || 0;

//                 console.log(`💸 Processing bid ${bid.bid_tx_id}: bet=${bidPoints}, win=${winningPoints}`);

//                 // Get user current balance
//                 const user = await user_module.findById(userDB_id).session(session);
//                 if (!user) {
//                     console.log(`⚠️ User ${userDB_id} not found, skipping bid`);
//                     continue;
//                 }

//                 const userBeforeBalance = user.wallet_balance;

//                 // Calculate total refund amount (bet amount + winning amount)
//                 const totalRefundAmount = bidPoints + winningPoints;

//                 if (totalRefundAmount > 0) {
//                     // Generate refund transaction token
//                     const refundTxToken = getUserRandomToken();

//                     // REFUND 1: Refund winning amount (deduct from user, add to admin)
//                     if (winningPoints > 0) {
//                         // Deduct winning amount from user
//                         await user_module.findByIdAndUpdate(
//                             userDB_id,
//                             { $inc: { wallet_balance: -winningPoints } },
//                             { session }
//                         );

//                         // Add winning amount to admin
//                         const adminUserId = 'your_admin_user_id_here'; // Replace with actual admin ID
//                         await user_module.findByIdAndUpdate(
//                             adminUserId,
//                             { $inc: { wallet_balance: winningPoints } },
//                             { session }
//                         );

//                         // Create transaction record for winning amount deduction from user
//                         await new wallet_trans_history_module({
//                             userDB_id: userDB_id,
//                             amount: winningPoints,
//                             transaction_type: 2, // Debit
//                             amount_status: 11, // Bid revert - winning amount deducted
//                             transaction_note: `Bid revert - winning amount deducted`,
//                             tx_request_number: refundTxToken + '_win',
//                             bid_tx_id: bid.bid_tx_id,
//                             open_result_token: open_result_token,
//                             before_wallet: userBeforeBalance,
//                             after_wallet: userBeforeBalance - winningPoints
//                         }).save({ session });

//                         // Create transaction record for winning amount addition to admin
//                         const adminUser = await user_module.findById(adminUserId).session(session);
//                         await new wallet_trans_history_module({
//                             userDB_id: adminUserId,
//                             amount: winningPoints,
//                             transaction_type: 1, // Credit
//                             amount_status: 12, // Bid revert - winning amount credited to admin
//                             transaction_note: `Bid revert - winning amount credited from user ${userDB_id}`,
//                             tx_request_number: refundTxToken + '_win_admin',
//                             bid_tx_id: bid.bid_tx_id,
//                             open_result_token: open_result_token,
//                             before_wallet: adminUser.wallet_balance,
//                             after_wallet: adminUser.wallet_balance + winningPoints
//                         }).save({ session });

//                         totalWinningRefunded += winningPoints;
//                     }

//                     // REFUND 2: Refund bet amount (add to user, deduct from admin)
//                     if (bidPoints > 0) {
//                         const userAfterWinDeduction = userBeforeBalance - winningPoints;

//                         // Add bet amount back to user
//                         await user_module.findByIdAndUpdate(
//                             userDB_id,
//                             { $inc: { wallet_balance: bidPoints } },
//                             { session }
//                         );

//                         // Deduct bet amount from admin
//                         const adminUserId = 'your_admin_user_id_here'; // Replace with actual admin ID
//                         await user_module.findByIdAndUpdate(
//                             adminUserId,
//                             { $inc: { wallet_balance: -bidPoints } },
//                             { session }
//                         );

//                         // Create transaction record for bet amount addition to user
//                         await new wallet_trans_history_module({
//                             userDB_id: userDB_id,
//                             amount: bidPoints,
//                             transaction_type: 1, // Credit
//                             amount_status: 13, // Bid revert - bet amount refunded
//                             transaction_note: `Bid revert - bet amount refunded`,
//                             tx_request_number: refundTxToken + '_bet',
//                             bid_tx_id: bid.bid_tx_id,
//                             open_result_token: open_result_token,
//                             before_wallet: userAfterWinDeduction,
//                             after_wallet: userAfterWinDeduction + bidPoints
//                         }).save({ session });

//                         // Create transaction record for bet amount deduction from admin
//                         const adminUser = await user_module.findById(adminUserId).session(session);
//                         const adminBeforeBetDeduction = adminUser.wallet_balance + winningPoints;
//                         await new wallet_trans_history_module({
//                             userDB_id: adminUserId,
//                             amount: bidPoints,
//                             transaction_type: 2, // Debit
//                             amount_status: 14, // Bid revert - bet amount deducted from admin
//                             transaction_note: `Bid revert - bet amount deducted for user ${userDB_id}`,
//                             tx_request_number: refundTxToken + '_bet_admin',
//                             bid_tx_id: bid.bid_tx_id,
//                             open_result_token: open_result_token,
//                             before_wallet: adminBeforeBetDeduction,
//                             after_wallet: adminBeforeBetDeduction - bidPoints
//                         }).save({ session });

//                         totalBetAmountRefunded += bidPoints;
//                     }

//                     console.log(`✅ Successfully processed refund for bid ${bid.bid_tx_id}`);
//                 }

//                 processedBidsCount++;

//             } catch (bidError) {
//                 console.error(`❌ Failed to process bid ${bid.bid_tx_id}:`, bidError);
//                 // Continue with other bids
//             }
//         }

//         // Step 4: Delete all wallet transaction records for this result
//         const deletedWalletTransactions = await wallet_trans_history_module.deleteMany({
//             open_result_token: open_result_token
//         }).session(session);

//         console.log(`🗑️ Deleted ${deletedWalletTransactions.deletedCount} wallet transaction records`);

//         // Step 5: Delete all bid documents for this game and date
//         const deletedBids = await starline_bid_history_module.deleteMany({
//             gameDB_id: gameDB_id,
//             bid_date: { $gte: startDate, $lte: endDate }
//         }).session(session);

//         console.log(`🗑️ Deleted ${deletedBids.deletedCount} bid documents`);

//         // Step 6: Delete user notifications
//         const deletedNotifications = await user_notification_module.deleteMany({
//             $or: [
//                 { open_result_token: open_result_token },
//                 { msg: { $regex: result.open_number, $options: 'i' } }
//             ]
//         }).session(session);

//         console.log(`🗑️ Deleted ${deletedNotifications.deletedCount} notification records`);

//         // Step 7: Finally delete the result history record
//         await starline_game_result_history_module.deleteOne({
//             _id: resultId
//         }).session(session);

//         console.log(`🗑️ Deleted result history record: ${resultId}`);

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

//         return res.status(200).json({
//             success: true,
//             message: "Complete bid revert successful",
//             data: {
//                 processedBidsCount: processedBidsCount,
//                 totalWinningRefunded: totalWinningRefunded,
//                 totalBetAmountRefunded: totalBetAmountRefunded,
//                 deletedBidsCount: deletedBids.deletedCount,
//                 deletedWalletTransactions: deletedWalletTransactions.deletedCount,
//                 deletedNotifications: deletedNotifications.deletedCount
//             }
//         });

//     } catch (error) {
//         await session.abortTransaction();
//         session.endSession();
//         console.error("❌ Error in completeStarlineBidRevert:", error);
//         return res.status(500).json({
//             success: false,
//             message: error.message
//         });
//     }
// };
const completeStarlineBidRevert = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const {
            gameDB_id,
            result_dec_date,
            resultId
        } = req.body;

        // console.log("🚀 ~ completeStarlineBidRevert ~ req.body:", req.body);
        console.log("🚀 ~ completeStarlineBidRevert ~ req.admin:", req.admin);

        if (!gameDB_id || !result_dec_date || !resultId) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Missing required fields: gameDB_id, result_dec_date, resultId"
            });
        }

        // Convert date to proper format
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        console.log(`🔍 Searching for result: ${resultId}`);

        // Step 1: Find the result document
        const result = await starline_game_result_history_module.findOne({
            _id: resultId,
            gameDB_id: gameDB_id,
            result_date: { $gte: startDate, $lte: endDate }
        }).session(session);

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "Result not found"
            });
        }

        console.log(`✅ Found result: ${result.open_number}, token: ${result.open_result_token}`);

        const open_result_token = result.open_result_token;

        // Step 2: Find all bids for this result
        const allBids = await starline_bid_history_module.find({
            gameDB_id: gameDB_id,
            bid_date: { $gte: startDate, $lte: endDate }
        }).session(session);

        console.log(`📊 Found ${allBids.length} bids to process`);

        let totalWinningDeducted = 0;
        let totalBetAmountRefunded = 0;
        let processedBidsCount = 0;

        // Step 3: Process winning amounts first (deduct from users, add to admin)
        console.log(`🔍 Processing winning amounts...`);

        for (const bid of allBids) {
            try {
                // Only process bids that have winning points (won bids)
                if (bid.winning_points > 0 && bid?.pay_status === 1) {
                    console.log("🚀 ~ completeStarlineBidRevert win result ~ bid:", bid)
                    const userDB_id = bid.userDB_id;
                    const winningAmount = bid.winning_points;
                    const bid_tx_id = bid.bid_tx_id;

                    console.log(`💸 Processing winning deduction for user ${userDB_id}, winning amount: ${winningAmount}`);

                    // Get user current balance
                    const user = await user_module.findById(userDB_id).session(session);
                    if (!user) {
                        console.log(`⚠️ User ${userDB_id} not found, skipping winning deduction`);
                        continue;
                    }

                    const userBeforeBalance = user.wallet_balance;

                    // Only process if user has sufficient balance
                    if (userBeforeBalance >= winningAmount) {
                        // DEDUCT winning amount from user (they received this when result was declared)

                        await user_module.findByIdAndUpdate(
                            userDB_id,
                            { $inc: { wallet_balance: -winningAmount } },
                            { session }
                        );

                        // ADD winning amount to admin (admin lost this when result was declared)
                        const adminUserId = req?.admin?._id; // Replace with actual admin ID
                        console.log("🚀 ~ completeStarlineBidRevert ~ adminUserId:", adminUserId)
                        const adminUser = await admin_module.findById(adminUserId).session(session);
                        const adminBeforeBalance = adminUser.wallet_amount;

                        await admin_module.findByIdAndUpdate(
                            adminUserId,
                            { $inc: { wallet_amount: winningAmount } },
                            { session }
                        );

                        // Create transaction record for winning amount deduction from user
                        // const refundTxToken = getUserRandomToken();
                        // await new wallet_trans_history_module({
                        //     userDB_id: userDB_id,
                        //     amount: winningAmount,
                        //     transaction_type: 2, // Debit
                        //     amount_status: 11, // Bid revert - winning amount deducted
                        //     transaction_note: `Bid revert - winning amount ${winningAmount} deducted`,
                        //     tx_request_number: refundTxToken + '_win_deduct',
                        //     bid_tx_id: bid_tx_id,
                        //     open_result_token: open_result_token,
                        //     before_wallet: userBeforeBalance,
                        //     after_wallet: userBeforeBalance - winningAmount
                        // }).save({ session });

                        // Create transaction record for winning amount addition to admin
                        // await new wallet_trans_history_module({
                        //     userDB_id: adminUserId,
                        //     amount: winningAmount,
                        //     transaction_type: 1, // Credit
                        //     amount_status: 12, // Bid revert - winning amount credited to admin
                        //     transaction_note: `Bid revert - winning amount ${winningAmount} credited from user ${userDB_id}`,
                        //     tx_request_number: refundTxToken + '_win_admin',
                        //     bid_tx_id: bid_tx_id,
                        //     open_result_token: open_result_token,
                        //     before_wallet: adminBeforeBalance,
                        //     after_wallet: adminBeforeBalance + winningAmount
                        // }).save({ session });

                        totalWinningDeducted += winningAmount;
                        console.log(`✅ Successfully deducted winning amount ${winningAmount} from user ${userDB_id} and added to admin`);
                    } else {
                        console.log(`⚠️ User ${userDB_id} has insufficient balance: ${userBeforeBalance}, required: ${winningAmount}`);
                    }
                }
            } catch (winningError) {
                console.error(`❌ Failed to process winning amount for bid ${bid.bid_tx_id}:`, winningError);
            }
        }

        // Step 4: Process bet amounts refund (add to users, deduct from admin)
        console.log(`🔍 Processing bet amount refunds...`);

        for (const bid of allBids) {
            try {
                const userDB_id = bid?.userDB_id;
                const betAmount = bid?.points || 0; // This is the original bet amount

                console.log(`💰 Processing bet refund for bid ${bid?.bid_tx_id}: bet amount=${betAmount}`);

                // Get user current balance (after winning deduction)
                const user = await user_module.findById(userDB_id).session(session);
                if (!user) {
                    console.log(`⚠️ User ${userDB_id} not found, skipping bet refund`);
                    continue;
                }

                const userBeforeBalance = user.wallet_balance;

                // REFUND: Refund bet amount (add to user, deduct from admin)
                if (betAmount > 0) {
                    // ADD bet amount back to user (they paid this when placing bid)
                    await user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: betAmount } },
                        { session }
                    );

                    // DEDUCT bet amount from admin (admin received this when bid was placed)
                    const adminUserId = req?.admin?._id; // Replace with actual admin ID
                    console.log("🚀 ~ completeStarlineBidRevert ~ adminUserId:", adminUserId)
                    const adminUser = await admin_module.findById(adminUserId).session(session);
                    const adminBeforeBalance = adminUser.wallet_amount;

                    await admin_module.findByIdAndUpdate(
                        adminUserId,
                        { $inc: { wallet_amount: - betAmount } },
                        { session }
                    );

                    // Create transaction record for bet amount addition to user
                    // const refundTxToken = getUserRandomToken();
                    // await new wallet_trans_history_module({
                    //     userDB_id: userDB_id,
                    //     amount: betAmount,
                    //     transaction_type: 1, // Credit
                    //     amount_status: 13, // Bid revert - bet amount refunded
                    //     transaction_note: `Bid revert - bet amount ${betAmount} refunded`,
                    //     tx_request_number: refundTxToken + '_bet_refund',
                    //     bid_tx_id: bid.bid_tx_id,
                    //     open_result_token: open_result_token,
                    //     before_wallet: userBeforeBalance,
                    //     after_wallet: userBeforeBalance + betAmount
                    // }).save({ session });

                    // Create transaction record for bet amount deduction from admin
                    // await new wallet_trans_history_module({
                    //     userDB_id: adminUserId,
                    //     amount: betAmount,
                    //     transaction_type: 2, // Debit
                    //     amount_status: 14, // Bid revert - bet amount deducted from admin
                    //     transaction_note: `Bid revert - bet amount ${betAmount} deducted for user ${userDB_id}`,
                    //     tx_request_number: refundTxToken + '_bet_admin',
                    //     bid_tx_id: bid.bid_tx_id,
                    //     open_result_token: open_result_token,
                    //     before_wallet: adminBeforeBalance,
                    //     after_wallet: adminBeforeBalance - betAmount
                    // }).save({ session });

                    totalBetAmountRefunded += betAmount;
                    console.log(`✅ Successfully refunded bet amount ${betAmount} to user ${userDB_id} and deducted from admin`);
                }

                processedBidsCount++;

            } catch (betError) {
                console.error(`❌ Failed to process bet refund for bid ${bid.bid_tx_id}:`, betError);
            }
        }

        // Step 5: Delete ALL wallet transaction records for this result token
        // This deletes both original bid placement transactions (amount_status: 5) and winning transactions (amount_status: 8)
        const deletedWalletTransactions = await wallet_trans_history_module.deleteMany({
            $or: [
                { open_result_token: open_result_token },
                {
                    tx_request_number: { $in: allBids.map(bid => bid.bid_tx_id) },
                    amount_status: 5 // Bid placement transactions
                }
            ]
        }).session(session);

        console.log(`🗑️ Deleted ${deletedWalletTransactions.deletedCount} wallet transaction records`);

        // Step 6: Delete all bid documents for this game and date
        const deletedBids = await starline_bid_history_module.deleteMany({
            gameDB_id: gameDB_id,
            bid_date: { $gte: startDate, $lte: endDate }
        }).session(session);

        console.log(`🗑️ Deleted ${deletedBids.deletedCount} bid documents`);

        // Step 7: Delete user notifications
        const deletedNotifications = await user_notification_module.deleteMany({
            $or: [
                { open_result_token: open_result_token },
                { msg: { $regex: result.open_number, $options: 'i' } }
            ]
        }).session(session);

        console.log(`🗑️ Deleted ${deletedNotifications.deletedCount} notification records`);

        // Step 8: Finally delete the result history record
        await starline_game_result_history_module.deleteOne({
            _id: resultId
        }).session(session);

        console.log(`🗑️ Deleted result history record: ${resultId}`);

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

        return res.status(200).json({
            success: true,
            message: "Complete bid revert successful",
            data: {
                processedBidsCount: processedBidsCount,
                totalWinningDeducted: totalWinningDeducted, // Amount deducted from users (winning amounts)
                totalBetAmountRefunded: totalBetAmountRefunded, // Amount refunded to users (bet amounts)
                deletedBidsCount: deletedBids.deletedCount,
                deletedWalletTransactions: deletedWalletTransactions.deletedCount,
                deletedNotifications: deletedNotifications.deletedCount
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.error("❌ Error in completeStarlineBidRevert:", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};






// const getOpenStarlineWinnerList = async (req, res) => {
//     try {
//         const { gameDB_id, result_dec_date} = req.body


//         let isDate;

//         isDate = moment_timeZone.tz(result_dec_date, "YYYY-MM-DD", "Asia/Kolkata");

//         if (req?.body?.winner) {
//             isDate = moment_timeZone.tz(result_dec_date, "DD-MMM-YYYY", "Asia/Kolkata");
//         }


//         console.log("🚀 ~ getOpenStarlineWinnerList ~ istDate:", isDate)

//         const startDate = isDate.clone().startOf("day").toDate();
//         console.log("🚀 ~ getOpenStarlineWinnerList ~ startDate:", startDate)
//         const endDate = isDate.clone().endOf("day").toDate();
//         console.log("🚀 ~ getOpenStarlineWinnerList ~ endDate:", endDate)

//         const result = await starline_game_result_history_module.find({
//             open_number: { $ne: '0' },
//             gameDB_id,
//             result_date: { $gte: startDate, $lte: endDate }
//         }).lean()

//         console.log("🚀 ~ getOpenStarlineWinnerList ~12630 result:", result)

//         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 filter = {
//                 $match: {
//                     gameDB_id,
//                     pay_status: 0,
//                     bid_date: { $gte: startDate, $lte: endDate },
//                 }
//             }

//             console.log("🚀 ~ getOpenStarlineWinnerList ~ filter:", filter)



//             const bid_data = await starline_bid_history_module.aggregate([
//                 // filter,
//                 {
//                     $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,
//                 //     },
//                 // },
//             ])

//             console.log("🚀 ~ getOpenStarlineWinnerList ~ bid_data:", bid_data)

//             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' });
//     }
// };


// starline winner list after result declare


const getOpenStarlineWinnerList = async (req, res) => {
    try {
        const { gameDB_id, result_dec_date } = req.body;
        const mongoose = require('mongoose');

        let isDate = moment_timeZone.tz(result_dec_date, "YYYY-MM-DD", "Asia/Kolkata");
        let pay_status = 0;

        if (req?.body?.winner) {
            isDate = moment_timeZone.tz(result_dec_date, "DD-MMM-YYYY", "Asia/Kolkata");
            pay_status = 1;
        }

        // console.log("🚀 ~ getOpenStarlineWinnerList ~ istDate:", isDate); 

        const startDate = isDate.clone().startOf("day").toDate();
        const endDate = isDate.clone().endOf("day").toDate();

        const result = await starline_game_result_history_module.find({
            open_number: { $ne: '0' },
            gameDB_id: new mongoose.Types.ObjectId(gameDB_id),
            result_date: { $gte: startDate, $lte: endDate }
        }).lean();

        // console.log("🚀 ~ getOpenStarlineWinnerList ~ result:", result);

        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_array = [];
        let win_amt_sum = 0;
        let points_amt_sum = 0;

        // Process each result
        for (const item of result) {
            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,
                        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,
                    },
                },
            ]);

            console.log("🚀 ~ getOpenStarlineWinnerList ~ bid_data:", bid_data);

            // Process each bid
            for (const bid of bid_data) {
                let win_amount = 0;
                let points = 0;

                if (bid.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 == bid.digits) {
                        win_amount = (single_digit_val_2 / single_digit_val_1) * bid.points;
                        points = bid.points;

                        data_array.push({
                            points: bid.points,
                            userDB_id: bid.userDB_id,
                            user_name: bid.user_name,
                            pana: bid.pana,
                            bid_tx_id: bid.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                } else if (bid.pana == 'Triple Pana') {
                    if (open_number == bid.digits) {
                        win_amount = (tripple_pana_val_2 / tripple_pana_val_1) * bid.points;
                        points = bid.points;

                        data_array.push({
                            points: bid.points,
                            userDB_id: bid.userDB_id,
                            user_name: bid.user_name,
                            pana: bid.pana,
                            bid_tx_id: bid.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                } else if (bid.pana == 'Double Pana') {
                    if (open_number == bid.digits) {
                        win_amount = (double_pana_val_2 / double_pana_val_1) * bid.points;
                        points = bid.points;

                        data_array.push({
                            points: bid.points,
                            userDB_id: bid.userDB_id,
                            user_name: bid.user_name,
                            pana: bid.pana,
                            bid_tx_id: bid.bid_tx_id,
                            win_amt: win_amount
                        });
                    }
                } else if (bid.pana == 'Single Pana') {
                    if (open_number == bid.digits) {
                        win_amount = (single_pana_val_2 / single_pana_val_1) * bid.points;
                        points = bid.points;

                        data_array.push({
                            points: bid.points,
                            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 += points;
            }
        }

        res.status(200).json({
            success: true,
            data: data_array,
            point: points_amt_sum,
            win_amt: win_amt_sum
        });

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



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

//         // Parse date as IST (input like "28-Oct-2025")
//         const istDate = moment_timeZone.tz(result_dec_date, "DD-MMM-YYYY", "Asia/Kolkata");

//         // Convert IST start and end of day to UTC for MongoDB
//         const startDate = istDate.clone().startOf("day").tz("UTC").toDate();
//         const endDate = istDate.clone().endOf("day").tz("UTC").toDate();

//         console.log("🚀 ~ startDate (UTC):", startDate);
//         console.log("🚀 ~ endDate (UTC):", endDate);

//         const result = await starline_game_result_history_module.find({
//             open_number: { $ne: '0' },
//             gameDB_id,
//             result_date: { $gte: startDate, $lte: endDate }
//         }).lean();

//         console.log("🚀 ~ getOpenStarlineWinnerList ~ result:", result);

//         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 filter = {
//         //         $match: {
//         //             gameDB_id: new ObjectId(gameDB_id), // ensure ObjectId match
//         //             pay_status: 0,
//         //             bid_date: { $gte: startDate, $lte: endDate },
//         //         },
//         //     };

//         //     console.log("🚀 ~ getOpenStarlineWinnerList ~ filter:", filter);

//         //     const bid_data = await starline_bid_history_module.aggregate([filter]);
//         //     console.log("🚀 ~ getOpenStarlineWinnerList ~ bid_data:", bid_data);

//         //     // ... rest of your logic stays the same ...
//         // }));

//         // res.status(200).json({
//         //     success: true,
//         //     data: data.data,
//         //     point: data.point,
//         //     win_amt: data.win_amt,
//         // });

//         const mappedResults = await Promise.all(
//             result.map(async (item) => {
//                 const open_number = item?.open_number;

//                 const filter = [
//                     {
//                         $match: {
//                             gameDB_id: new ObjectId(gameDB_id),
//                             // pay_status: 0, // remove or modify this
//                             bid_date: { $gte: startDate, $lte: endDate },
//                         },
//                     },
//                     {
//                         $lookup: {
//                             from: "users",
//                             localField: "userDB_id",
//                             foreignField: "_id",
//                             as: "user",
//                         },
//                     },
//                     {
//                         $unwind: {
//                             path: "$user",
//                             preserveNullAndEmptyArrays: true,
//                         },
//                     },
//                     {
//                         $project: {
//                             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 bid_data = await starline_bid_history_module.aggregate([filter]);
//                 console.log("🚀 ~ getOpenStarlineWinnerList ~ bid_data:", bid_data);

//                 const data_array = [];
//                 let win_amt_sum = 0;
//                 let points_amt_sum = 0;

//                 bid_data.forEach((item) => {
//                     let win_amount = 0;
//                     let points = 0;

//                     if (item.pana === "Triple Pana" && open_number === item.digits) {
//                         win_amount = (game_rate.tripple_pana_val_2 / game_rate.tripple_pana_val_1) * item.points;
//                         points = item.points;
//                         data_array.push({
//                             points: item.points,
//                             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,
//                 };
//             })
//         );

//         const data = mappedResults[0]; // first result if only one
//         if (!data) {
//             return res.status(200).json({ success: true, data: [], point: 0, win_amt: 0 });
//         }

//         return 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;


        if (!result_dec_date || !gameDB_id) {
            return res.status(400).json({ success: false, msg: "Result date and game Id not found !" });
        }

        const gameData = await starline_games_module.findById(gameDB_id);
        let gameName = '';

        if (!gameData) {
            return res.status(400).json({ success: false, msg: "Game data not found !" });
        } else {
            gameName = gameData.game_name;
        }


        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();


                const userData = await user_module.findById(userDB_id);
                let beforeUserWalletAmount = 0;
                if (userData) {
                    beforeUserWalletAmount += userData?.wallet_balance;
                }


                await Promise.all([
                    user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: win_amt } },
                        { new: true, session }
                    ),
                    admin_module.findByIdAndUpdate(
                        req?.admin?._id, { $inc: { wallet_amount: -win_amt } }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        starline_gameDB_id: gameDB_id,
                        amount: win_amt,
                        transaction_type: 1,
                        amount_status: 8,
                        transaction_note: msg,
                        before_wallet: beforeUserWalletAmount,
                        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 });
        }

        // call or send the firebase live notification when result declare for starline game
        const SLMsg = await sendFBNotification(
            `${gameName}`,
            `${open_number}-${win_number_not}`,
            '',
            {} // no res → internal call
        );

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

        return res.status(200).json({ success: true, message: "Open result declared successfully", SLMsg });

    } 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",
            "status",  // "Active",
            "market_status",  // "Market Status",
            "close_time",  // "Today Close",
        ]

        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 Gali Disswar 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({});
        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 (gameDB_id !== "all" && !mongoose.isValidObjectId(gameDB_id)) {
            return res.status(400).json({ success: false, msg: "Invalid gameDB_id." });
        }
        // console.log("start end date-", startDate, endDate)
        const matchFilter = {
            pay_status: 0,
            // bid_date: { $gte: startDate, $lte: endDate },
        };

        if (gameDB_id !== 'all') {
            matchFilter.gameDB_id = new mongoose.Types.ObjectId(gameDB_id)
        }

        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,
                    insert_date: 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,
                insert_date: v?.insert_date,
            };

            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 } = req.body;

        console.log("🚀 ~ getGalidisswarSellReport ~ gameDB_id:", gameDB_id, gameType)
        if (!gameDB_id) {
            return res.status(400).json({ success: false, msg: "Missing gameDB_id." });
        }

        if (gameDB_id !== "all" && !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 = {
            bid_date: { $gte: startDate, $lte: endDate }
        };

        if (gameDB_id !== "all") {
            baseFilter.gameDB_id = new mongoose.Types.ObjectId(gameDB_id);
        }

        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 updateMiniGamesSettings = async (req, res) => {
    try {
        const games = req.body;
        if (!Array.isArray(games) || games.length === 0) {
            return res.status(400).json({ message: "Invalid payload" });
        }

        // prepare bulk operations
        const bulkOps = games.map((game) => ({
            updateOne: {
                filter: { _id: game._id },
                update: { $set: { status: game.status } },
            },
        }));

        // execute all updates in one go
        await mini_games_module.bulkWrite(bulkOps);

        return res.json({ success: true, message: "Game statuses updated successfully" });
    }
    catch (err) {
        return res.status(400).json({ message: "Invalid payload" });

    }
}

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 archive_totalBidAmount = await bid_archive_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" }
                }
            }
        ])
        const total_winAmount = await wallet_trans_history_module.aggregate([
            {
                $match: {
                    amount_status: { $eq: 8 }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount" }
                }
            }
        ])
        const archive_total_winAmount = await wallet_trans_archive_history_module.aggregate([
            {
                $match: {
                    amount_status: { $eq: 8 }
                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount" }
                }
            }
        ])
        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 wallet_trans_history_module.aggregate([
            {
                $match: {
                    insert_date: { $gte: startDate, $lte: endDate },
                    //  amount_status : 1
                    amount_status: { $in: [1, 19] }

                }
            },
            {
                $group: {
                    _id: null,
                    total: { $sum: "$amount" }
                }
            }
        ]);

        console.log("total deposit-", today_totalDeposit_amount)
        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 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_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);
        //     return total;
        // };
        // console.log("bid amount Daashboard")
        // console.log("---------", `${today_totalBidAmount[0]?.total} ---------   ${today_totalwinAmount[0]?.total}-------------  ${totalBidAmount_gali_disswar[0]?.total}  --------------- ${total_winAmount[0]?.total}        `)
        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),
            today_total_bid_amount: today_totalBidAmount[0]?.total || 0,
            total_bid_amount: (totalBidAmount[0]?.total || 0) + (archive_totalBidAmount[0]?.total || 0), // total_bid_amount(),

            today_winning_amount: today_totalwinAmount[0]?.total || 0,
            total_winning_amount: (total_winAmount[0]?.total || 0) + (archive_total_winAmount[0]?.total || 0),

            today_profit: (today_totalBidAmount[0]?.total || 0) - (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_profit: ((totalBidAmount[0]?.total || 0) + (archive_totalBidAmount[0]?.total || 0)) - ((total_winAmount[0]?.total || 0) + (archive_total_winAmount[0]?.total || 0)),




            today_total_withdraw: today_totalWithdraw_amount[0]?.total || 0,
            today_total_deposit: today_totalDeposit_amount[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,
            admin_wallet_amount: req.admin ? req.admin.wallet_amount : 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 {
                _id: rs._id,
                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;
        console.log("🚀 ~ saveGalidisswarGameData ~ req?.body:", req?.body)

        // Check for required fields
        if (!pana_number || !gameDB_id || !result_dec_date) {
            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
        console.log("🚀 ~ getGalidisswarWinnerList_declare ~ gameDB_id, result_dec_date :", gameDB_id, 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();

        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,
                    },
                },
            ])

            console.log("🚀 ~ getGalidisswarWinnerList_declare ~ bid_data:", bid_data)
            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;

        if (!result_dec_date || !gameDB_id) {
            return res.status(400).json({ success: false, msg: "Result date and game Id not found !" });
        }

        const gameData = await gali_disswar_games_module.findById(gameDB_id);
        let gameName = '';

        if (!gameData) {
            return res.status(400).json({ success: false, msg: "Game data not found !" });
        } else {
            gameName = gameData.game_name;
        }

        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);

        // Use the correct field names from your document
        const red_bracket_val_1 = parseFloat(game_rate.red_bracket_val_1) || 1;
        const red_bracket_val_2 = parseFloat(game_rate.red_bracket_val_2) || 100;
        const group_jodi_val_1 = parseFloat(game_rate.group_jodi_val_1) || 1;
        const group_jodi_val_2 = parseFloat(game_rate.group_jodi_val_2) || 50;
        const jodi_digit_val_1 = parseFloat(game_rate.jodi_digit_val_1) || 1;
        const jodi_digit_val_2 = parseFloat(game_rate.jodi_digit_val_2) || 10;

        const close_result_token = uniqRandom(15);

        const adminData = req.admin || null;
        if (!adminData || !adminData._id) {
            return res.status(401).json({ success: false, msg: 'Admin not found' });
        }

        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':
                // case 'Right Digit':
                //     // For single digit bets, check if the digit matches
                //     if (winSingleDigit == digits) {
                //         // For single digits, typically the payout is 1:9.5 or similar
                //         // Adjust this based on your actual single digit rates
                //         win_amt = points * 9.5; // Adjust multiplier as needed
                //         matched = true;
                //     }
                //     break;

                case 'Jodi Digit':
                    if (close_number == digits) {
                        win_amt = (jodi_digit_val_2 / jodi_digit_val_1) * points;
                        matched = true;
                    }
                    break;

                case 'Group Jodi':
                    if (close_number == digits) {
                        win_amt = (group_jodi_val_2 / group_jodi_val_1) * points;
                        matched = true;
                    }
                    break;

                case 'Red Bracket':
                    if (close_number == digits) {
                        win_amt = (red_bracket_val_2 / red_bracket_val_1) * points;
                        matched = true;
                    }
                    break;
            }

            if (matched) {
                const msg = `${item.game_name} in ${pana} for bid amount- ${points} Won`;
                const tx_token = getUserRandomToken();

                console.log("🚀 winning bet, req.admin:", req.admin)
                if (req.admin.wallet_amount < win_amt) {
                    await session.abortTransaction();
                    session.endSession();
                    return res.status(400).json({ success: false, message: "Insufficient wallet amount in admin account." });
                }


                const userData = await user_module.findById(userDB_id).session(session);
                console.log("🚀 ~ decleareGalidisswarData ~ userData:", userData)
                if (!userData) {
                    await session.abortTransaction();
                    session.endSession();
                    return res.status(400).json({ success: false, message: "User not found." });
                }



                await Promise.all([
                    user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: win_amt } },
                        { new: true, session }
                    ),
                    admin_module.findByIdAndUpdate(
                        req.admin._id,
                        { $inc: { wallet_amount: -win_amt } },
                        { new: true, session }
                    ),
                    new wallet_trans_history_module({
                        userDB_id,
                        jackpot_gameDB_id: gameDB_id,
                        amount: win_amt,
                        transaction_type: 1,
                        amount_status: 8,
                        transaction_note: msg,
                        tx_request_number: tx_token,
                        bid_tx_id,
                        close_result_token,
                        before_wallet: userData?.wallet_balance,
                        admin_type: adminData?.admin_type,
                        admin_name: adminData?.username
                    }).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: { close_result_token, 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 });
        // }


        // call or send the firebase live notification when result declare for starline game
        // const SLMsg = await sendFBNotification(
        //     "Jackpot result declared !",
        //     `Jackpot game result is announced ${close_number} on ${result_dec_date} `,
        //     {} // no res → internal call
        // );

        // call or send the firebase live notification when result declare for starline game
        const SLMsg = await sendFBNotification(
            `${gameName}`,
            `${close_number}`,
            '',
            {} // no res → internal call
        );




        await session.commitTransaction();
        session.endSession();
        return res.status(200).json({ success: true, message: "Close result declared successfully" });

    } catch (err) {
        console.error("declareData error:", err);
        await session.abortTransaction();
        session.endSession();
        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 {
        const baseUrl = process?.env?.BASE_URL;
        if (!baseUrl) {
            return res.status(500).json({ success: false, msg: "Base URL not set" });
        }

        const { qr_title = "Pay here", description = '', upi_id = '' } = 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({
            qr_title,
            description,
            upi_id,
            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 processResultRefund = async ({ admin_id, result_token, open_token, session_type, gameDB_id, resultDate, mongooseSession }) => {
    console.log("🚀 ~ processResultRefund ~ result_token:", result_token, "open token ", open_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);

        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 not, use available balance
                const actualDeductAmount = Math.min(refundAmount, userData.wallet_balance);

                console.log("🚀 ~ processResultRefund ~ actualDeductAmount:", actualDeductAmount)
                if (actualDeductAmount > 0) {
                    // Generate unique transaction token
                    // const refundTxToken = getUserRandomToken();

                    // Create refund transaction record - UNCOMMENTED THIS
                    // await new wallet_trans_history_module({
                    //     userDB_id,
                    //     amount: actualDeductAmount,
                    //     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 - actualDeductAmount
                    // }).save({ session: mongooseSession });

                    // Deduct amount from user wallet
                    await user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: -actualDeductAmount } },
                        { new: true, session: mongooseSession }
                    );

                    if (admin_id) {
                        await admin_module.findByIdAndUpdate(admin_id, { $inc: { wallet_amount: actualDeductAmount } });
                    }

                    console.log(`✅ Successfully deducted ${actualDeductAmount} from user ${userDB_id}`);
                } else {
                    console.warn(`⚠️ User ${userDB_id} has insufficient balance for refund. Available: ${userData.wallet_balance}, Required: ${refundAmount}`);
                }
            }

            // Update bid status to 0 (not won) and pay_status to 0 (not paid) and reset winning_points


            let bidUpdateData = {
                pay_status: 0
            }

            if (bid?.open_result_token) {
                bidUpdateData.open_result_token = null
            }
            if (bid?.close_result_token) {
                bidUpdateData.close_result_token = null
            }

            console.log("🚀 ~ processResultRefund ~ bidUpdateData:", bidUpdateData)


            await bid_history_module.updateOne(
                { _id: bid._id },
                {
                    // $set: {
                    //     status: 0, // Reset bid status to not won
                    //     pay_status: 0, // Reset payment status to not paid
                    //     winning_points: 0 // Reset winning points to 0
                    // }
                    $set: bidUpdateData
                },
                { session: mongooseSession }
            );

            console.log(`✅ Updated bid ${bid._id} status to 0, pay_status to 0, and reset winning_points`);
        }

        // 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);

        console.log(`✅ Deleted wallet transactions for ${session_type} result token: ${result_token}`);

    } catch (error) {
        console.error(`Error processing ${session_type} result refund:`, error);
        throw error;
    }
};

// Main delete function with session type parameter
const deleteResultData = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date, resultId, deleteType = 'both' } = req.body;

        console.log("req.body of 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("🚀 ~ deleteResultData ~ 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"
            });
        }

        // Check if sessions are already processed (status = 0)
        if (deleteType === 'both' || deleteType === 'open') {
            if (result.open_decleare_status === 0) {
                await session.abortTransaction();
                session.endSession();
                return res.status(400).json({
                    success: false,
                    message: "Open result is already deleted or not declared"
                });
            }
        }

        if (deleteType === 'both' || deleteType === 'close') {
            if (result?.close_decleare_status === 0 && result?.open_decleare_status === 0) {
                await session.abortTransaction();
                session.endSession();
                return res.status(400).json({
                    success: false,
                    message: "Close result is already deleted or not declared"
                });
            }
        }

        // 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("🚀 ~ deleteResultData ~ open_result_token:", open_result_token);
        console.log("🚀 ~ deleteResultData ~ close_result_token:", close_result_token);

        // Track what was processed
        let processedSessions = [];

        // Process based on deleteType
        if (deleteType === 'both' || deleteType === 'open') {
            if (open_result_token && result.open_decleare_status === 1) {
                if (req?.admin?._id) {

                    await processResultRefund({
                        admin_id: req?.admin?._id,
                        result_token: open_result_token,
                        session_type: 'open',
                        gameDB_id,
                        resultDate,
                        mongooseSession: session
                    });
                    processedSessions.push('open');
                } else {
                    return res.status(400).json({
                        success: false,
                        message: "Admin details not found"
                    });
                }
            }
        }

        if (deleteType === 'both' || deleteType === 'close') {
            if (open_result_token && result?.open_decleare_status === 1 && close_result_token && result.close_decleare_status === 1) {

                if (req?.admin?._id) {
                    await processResultRefund({
                        admin_id: req?.admin?._id,
                        result_token: close_result_token,
                        open_token: open_result_token,
                        session_type: 'close',
                        gameDB_id,
                        resultDate,
                        mongooseSession: session
                    });
                    processedSessions.push('close');
                } else {
                    return res.status(400).json({
                        success: false,
                        message: "Admin details not found"
                    });
                }

            }
        }

        // If no sessions were declared, no need to proceed with deletions
        if (processedSessions.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "No declared sessions found to delete"
            });
        }

        // Delete user notifications dynamically for processed sessions only
        let notificationOr = [];
        if ((deleteType === 'both' || deleteType === 'open') && result.open_number && result.open_decleare_status === 1) {
            notificationOr.push({ msg: { $regex: result.open_number, $options: 'i' } });
        }
        if ((deleteType === 'both' || deleteType === 'close') && result.close_number && result.close_decleare_status === 1) {
            notificationOr.push({ msg: { $regex: result.close_number, $options: 'i' } });
        }

        if (notificationOr.length > 0) {
            await user_notification_module.deleteMany({
                $or: notificationOr
            }).session(session);
            console.log(`✅ Deleted notifications for sessions: ${processedSessions.join(', ')}`);
        }

        // Update result document based on deleteType
        if (deleteType === 'both') {
            // Delete the entire result document
            await game_result_history_module.deleteOne({
                _id: resultId,
                gameDB_id,
                result_date: resultDate
            }).session(session);
            console.log(`✅ Completely deleted result document for ${resultDate}`);
        } else {
            // Update specific session data
            const updateData = {};
            if (deleteType === 'open') {
                updateData.open_result_token = null;
                updateData.open_number = null;
                updateData.open_pana = null;
                updateData.open_decleare_status = 0;
                updateData.open_decleare_date = null;
            } else if (deleteType === 'close') {
                updateData.close_result_token = null;
                updateData.close_number = null;
                updateData.close_pana = null;
                updateData.close_decleare_status = 0;
                updateData.close_decleare_date = null;
            }

            await game_result_history_module.updateOne(
                {
                    _id: resultId,
                    gameDB_id,
                    result_date: resultDate
                },
                { $set: updateData },
                { session }
            );
            console.log(`✅ Updated ${deleteType} session data to reset values`);
        }

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

        return res.status(200).json({
            success: true,
            message: `Deleted ${processedSessions.join(' and ')} result(s) successfully. Winning amounts deducted from user wallets for declared sessions. All bid statuses reset to 0.`,
            data: {
                deletedSessions: processedSessions,
                deleteType: deleteType
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("Error in deleteResultData", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};

// Separate endpoint for deleting both results
const deleteOpenCloseResultData_Result = async (req, res) => {
    req.body.deleteType = 'both';
    return deleteResultData(req, res);
};

// Separate endpoint for deleting open result only
const deleteOpenResultData_Result = async (req, res) => {
    req.body.deleteType = 'open';
    return deleteResultData(req, res);
};

// Separate endpoint for deleting close result only
const deleteCloseResultData_Result = async (req, res) => {
    req.body.deleteType = 'close';
    return deleteResultData(req, res);
};








// main game complete bid revert for both/open/close sesstion main function
const revertBids = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date, resultId, revertType = 'both' } = req.body;

        console.log("🚀 ~ revertBids ~ 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"
            });
        }

        // Parse the date for range filtering
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf('day').toDate();
        const endDate = istDate.clone().endOf('day').toDate();
        console.log("Date range for bids:", { startDate, endDate });

        // 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: Build dynamic $or based on revertType
        let orConditions = [];

        if (revertType === 'both' || revertType === 'open') {
            if (open_result_token && gameResult.open_decleare_status === 1) {
                orConditions.push({ open_result_token: open_result_token });
            }
        }

        if (revertType === 'both' || revertType === 'close') {
            if (close_result_token && gameResult.close_decleare_status === 1) {
                orConditions.push({ close_result_token: close_result_token });
            }
        }

        if (orConditions.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "No declared sessions found to revert"
            });
        }

        // Build the query with date range
        const query = {
            $or: orConditions,
            gameDB_id: gameDB_id,
            bid_date: {
                $gte: startDate,
                $lte: endDate
            }
        };

        console.log("🔍 Query for bids:", JSON.stringify(query, null, 2));

        // Find ALL bids associated with declared result tokens
        const allBids = await bid_history_module.find(query).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 declared sessions in 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 {
                if (req?.admin?._id) {

                    const refundResult = await processSingleBidRevert({
                        admin_id: req?.admin?._id,
                        bid,
                        session
                    });

                    totalRefundedAmount += refundResult.refundAmount;
                    totalBidAmount += refundResult.bidAmount;
                    totalWinningAmount += refundResult.winningAmount;
                    revertedBidsCount++;

                    console.log(`✅ Successfully reverted bid: ${bid.bid_tx_id}, refunded: ${refundResult.refundAmount}`);
                } else {
                    return res.status(400).json({ success: false, message: "Admin Details not found for revert amount!" });
                }
            } catch (bidError) {
                console.error(`❌ Failed to revert bid ${bid.bid_tx_id}:`, bidError);
                // Continue with other bids even if one fails
                return res.status(500).json({ success: false, message: "Internal Server Error", error: bidError });
            }
        }

        // Step 4: Update or delete the game result document based on revertType
        if (revertType === 'both') {
            // Delete the entire game result document
            await game_result_history_module.deleteOne({
                _id: resultId,
                gameDB_id: gameDB_id,
                result_date: resultDate
            }).session(session);
            console.log(`🗑️ Deleted complete game result: ${resultId}`);
        } else {
            // Update specific session data only
            const updateData = {};
            if (revertType === 'open') {
                updateData.open_result_token = null;
                updateData.open_number = null;
                updateData.open_pana = null;
                updateData.open_decleare_status = 0;
                updateData.open_result_declare_date = null;
            } else if (revertType === 'close') {
                updateData.close_result_token = null;
                updateData.close_number = null;
                updateData.close_pana = null;
                updateData.close_decleare_status = 0;
                updateData.close_result_declare_date = null;
            }

            await game_result_history_module.updateOne(
                {
                    _id: resultId,
                    gameDB_id: gameDB_id,
                    result_date: resultDate
                },
                { $set: updateData },
                { session }
            );
            console.log(`🔄 Updated ${revertType} session data for game result: ${resultId}`);
        }

        // Step 5: Delete user notifications dynamically for processed sessions only
        let notificationOr = [];
        if ((revertType === 'both' || revertType === 'open') && gameResult.open_number && gameResult.open_decleare_status === 1) {
            notificationOr.push({ msg: { $regex: gameResult.open_number, $options: 'i' } });
        }
        if ((revertType === 'both' || revertType === 'close') && gameResult.close_number && gameResult.close_decleare_status === 1) {
            notificationOr.push({ msg: { $regex: gameResult.close_number, $options: 'i' } });
        }

        if (notificationOr.length > 0) {
            await user_notification_module.deleteMany({
                $or: notificationOr
            }).session(session);
            console.log(`🗑️ Deleted related notifications`);
        }

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

        return res.status(200).json({
            success: true,
            message: `Successfully reverted ${revertedBidsCount} bids for ${revertType} session(s). Total refunded: ${totalRefundedAmount} points.`,
            data: {
                revertedBidsCount,
                totalRefundedAmount,
                totalBidAmount,
                totalWinningAmount,
                revertType: revertType,
                [revertType === 'both' ? 'deletedResult' : 'updatedResult']: resultId
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertBids", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};

// Separate endpoint for reverting both sessions
const revertBidCompletely = async (req, res) => {
    req.body.revertType = 'both';
    return revertBids(req, res);
};

// Separate endpoint for reverting open bids only
const revertOpenBids = async (req, res) => {
    req.body.revertType = 'open';
    return revertBids(req, res);
};

// Separate endpoint for reverting close bids only
const revertCloseBids = async (req, res) => {
    req.body.revertType = 'close';
    return revertBids(req, res);
};



// --------------------------------------------------seprate the game result delete & complete bid revert with the bid rever submenu------------------------------------------------------










//bid revert sub menu for only revret the placed bid

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

    try {
        const { bid_id, user_id, amount } = req.body;

        console.log("🔄 revertSingleBid ~ req.body:", req.body);

        if (!bid_id || !user_id || !amount) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Bid ID, User ID and Amount are required"
            });
        }

        // Step 1: Find and delete the bid
        const bid = await bid_history_module.findById(bid_id).session(session);
        if (!bid) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "Bid not found"
            });
        }

        console.log("🗑️ Deleting bid:", bid.bid_tx_id);
        await bid_history_module.deleteOne({ _id: bid_id }).session(session);

        // Step 2: Add amount back to user wallet
        const user = await user_module.findById(bid.userDB_id).session(session);
        if (!user) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "User not found"
            });
        }

        const originalBalance = user.wallet_balance;
        user.wallet_balance += amount;
        await user.save({ session });

        console.log("req?.admin?._id", req?.admin?._id)
        const adminAmountUpdate = await admin_module.findByIdAndUpdate(req?.admin?._id, { $inc: { wallet_amount: -amount } })
        console.log("🚀 ~ revertSingleBid ~ adminAmountUpdate:", adminAmountUpdate)

        console.log(`💰 Wallet updated: ${user.user_name} - ${originalBalance} -> ${user.wallet_balance}`);

        // Step 3: Delete original bid transaction using tx_request_number
        const deleteResult = await wallet_trans_history_module.deleteMany({
            tx_request_number: bid.bid_tx_id // Use tx_request_number instead of bid_tx_id
        }).session(session);

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} wallet transactions for bid: ${bid.bid_tx_id}`);

        // If no transactions were found/deleted, log it but don't fail
        if (deleteResult.deletedCount === 0) {
            console.log(`⚠️ No wallet transactions found for tx_request_number: ${bid.bid_tx_id}`);

            // Let's also try to find what transactions exist for this user
            const userTransactions = await wallet_trans_history_module.find({
                userDB_id: bid.userDB_id,
                amount_status: 5 // bid placed
            }).session(session);

            console.log(`🔍 Found ${userTransactions.length} bid transactions for user:`,
                userTransactions.map(t => ({
                    tx_request_number: t.tx_request_number,
                    amount: t.amount,
                    bid_tx_id: t.bid_tx_id // Check if this field exists
                }))
            );
        }

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

        return res.status(200).json({
            success: true,
            message: `Bid reverted successfully. Amount ₹${Number(amount).toFixed(2)} added back to wallet.`,
            data: {
                refundedAmount: Number(amount),
                userNewBalance: user.wallet_balance,
                bid_tx_id: bid.bid_tx_id,
                deletedTransactions: deleteResult.deletedCount
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertSingleBid", error);
        return res.status(500).json({
            success: false,
            message: "Failed to revert bid: " + error.message
        });
    }
};

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

    try {
        const { bid_ids, bids_data } = req.body;

        console.log("🔄 revertMultipleBids ~ Processing", bid_ids?.length, "bids");

        if (!bid_ids || !Array.isArray(bid_ids) || bid_ids.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Bid IDs are required"
            });
        }

        let totalRefunded = 0;
        let revertedCount = 0;
        const userSummary = {};

        // Step 1: Delete all bids first
        const deleteResult = await bid_history_module.deleteMany({
            _id: { $in: bid_ids }
        }).session(session);

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} bids from database`);

        // Step 2: Process wallet updates for each user
        for (const bidData of bids_data) {
            const { userDB_id, amount } = bidData;

            if (!userSummary[userDB_id]) {
                userSummary[userDB_id] = {
                    user: await user_module.findById(userDB_id).session(session),
                    totalRefunded: 0
                };
            }

            const userData = userSummary[userDB_id];

            if (userData.user) {
                userData.totalRefunded += Number(amount);
                totalRefunded += Number(amount);
                revertedCount++;
            }
            await admin_module.findByIdAndUpdate(req?.admin?._id, { $inc: { wallet_amount: -amount } });
        }

        // Step 3: Update all user wallets
        for (const userId in userSummary) {
            if (userSummary[userId].user && userSummary[userId].totalRefunded > 0) {
                const originalBalance = userSummary[userId].user.wallet_balance;
                userSummary[userId].user.wallet_balance += userSummary[userId].totalRefunded;
                await userSummary[userId].user.save({ session });

                console.log(`💰 Wallet updated for ${userSummary[userId].user.user_name}: ${originalBalance} -> ${userSummary[userId].user.wallet_balance}`);
            }
        }

        // Step 4: Delete all original bid transactions (no refund transactions created)

        const deletedTransactions = await wallet_trans_history_module.deleteMany({
            tx_request_number: { $in: bids_data.map(bid => bid.bid_tx_id) }
        }).session(session);

        console.log(`🗑️ Deleted ${deleteResult.deletedCount} wallet transactions for multiple bids`);

        console.log(`🗑️ Deleted ${deletedTransactions.deletedCount} original bid transactions`);

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

        // Prepare response
        const userRefundDetails = Object.keys(userSummary)
            .filter(userId => userSummary[userId].totalRefunded > 0)
            .map(userId => ({
                user_id: userId,
                user_name: userSummary[userId].user?.user_name || 'Unknown',
                refunded_amount: userSummary[userId].totalRefunded,
                new_balance: userSummary[userId].user?.wallet_balance || 0
            }));

        return res.status(200).json({
            success: true,
            message: `Successfully reverted ${revertedCount} bids. Total amount returned: ₹${totalRefunded.toFixed(2)}`,
            data: {
                revertedCount,
                totalRefunded,
                userRefundDetails
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertMultipleBids", error);
        return res.status(500).json({
            success: false,
            message: "Failed to revert bids: " + error.message
        });
    }
};




const processSingleBidRevert = async ({ admin_id, 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 }
            );

            if (admin_id) {
                await admin_module.findByIdAndUpdate(admin_id, { $inc: { wallet_amount: -Math.abs(netAdjustment) } })
            }


        } 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 }
            );

            if (admin_id) {
                await admin_module.findByIdAndUpdate(admin_id, { $inc: { wallet_amount: Math.abs(netAdjustment) } })
            }
        }

        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 refundStarlineWinnings(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) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date } = req.body;

        if (!gameDB_id || !result_dec_date) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                msg: 'Missing required fields: gameDB_id and result_dec_date'
            });
        }

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

        // Convert date to proper format
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf("day").toDate();
        const endDate = istDate.clone().endOf("day").toDate();

        // Find the starline result
        const result = await starline_game_result_history_module.findOne({
            gameDB_id: gameDB_id,
            result_date: { $gte: startDate, $lte: endDate },
            open_decleare_status: 1 // Only delete declared results
        }).session(session);

        if (!result) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                msg: "Starline result not found or not declared yet"
            });
        }

        const open_result_token = result.open_result_token;
        const open_number = result.open_number;

        console.log(`🔍 Processing reversal for result token: ${open_result_token}, Number: ${open_number}`);

        // Step 1: Find ALL bids for this result token (both winning and losing)
        const allBids = await starline_bid_history_module.find({
            open_result_token: open_result_token
        }).session(session);

        console.log(`📊 Found ${allBids.length} bids to process`);

        // Step 2: Find winning bids that were paid (pay_status: 1) to revert amounts
        const winningBids = allBids.filter(bid => bid.pay_status === 1);
        console.log(`💰 Found ${winningBids.length} winning bids to revert amounts`);

        // Step 3: Revert winning amounts from user wallets and add to admin
        let totalRevertedAmount = 0;
        const userRefundPromises = [];
        const walletTransactionDeletePromises = [];

        for (const bid of winningBids) {
            const userId = bid.userDB_id; // Using userDB_id from your data
            const winningAmount = bid.winning_points || 0; // Using winning_points from your data

            if (winningAmount > 0) {
                totalRevertedAmount += winningAmount;

                // Revert from user wallet (deduct winning amount)
                userRefundPromises.push(
                    user_module.findByIdAndUpdate(
                        userId,
                        {
                            $inc: {
                                wallet_balance: -winningAmount
                                // Note: Your user schema doesn't have total_winning field
                            }
                        },
                        { session }
                    )
                );

                console.log(`💰 Reverting ${winningAmount} from user ${userId}`);
            }
        }

        console.log("req admin id ", req?.admin?._id)

        // Step 4: Add reverted amount to admin wallet
        if (totalRevertedAmount > 0) {
            await admin_module.findByIdAndUpdate(
                req?.admin?._id, // Your admin ID
                {
                    $inc: {
                        wallet_amount: totalRevertedAmount
                    }
                },
                { session }
            );
            console.log(`💼 Added ${totalRevertedAmount} to admin wallet`);
        }

        // Execute all user wallet operations
        await Promise.all(userRefundPromises);

        // Step 5: Delete ALL wallet transaction records related to winning for this result
        const deleteWalletTransactions = await wallet_trans_history_module.deleteMany({
            open_result_token: open_result_token,
            transaction_type: 1, // Winning transactions (type 1 from your data)
            amount_status: 8 // Winning amount status
        }).session(session);

        console.log(`🗑️ Deleted ${deleteWalletTransactions.deletedCount} winning wallet transaction records`);

        // Step 6: Update ALL bids - reset pay_status and remove open_result_token
        const updateBidsResult = await starline_bid_history_module.updateMany(
            {
                gameDB_id: gameDB_id,
                bid_date: { $gte: startDate, $lte: endDate }
            },
            {
                $set: {
                    pay_status: 0, // Reset to not paid
                    open_result_token: null, // Remove result token
                }
            },
            { session }
        );

        console.log(`🔄 Updated ${updateBidsResult.modifiedCount} bid records to pending status`);

        // Step 7: Delete the result document
        const deleteResult = await starline_game_result_history_module.deleteOne({
            _id: result._id
        }).session(session);

        console.log(`🗑️ Deleted result document: ${result._id}`);

        // Step 8: Delete user notifications related to this result
        const deleteNotificationsResult = await user_notification_module.deleteMany({
            $or: [
                { open_result_token: open_result_token },
                { msg: { $regex: open_number.toString(), $options: 'i' } }
            ]
        }).session(session);

        console.log(`🔔 Deleted ${deleteNotificationsResult.deletedCount} notification records`);

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

        return res.json({
            success: true,
            msg: "Starline result successfully deleted and all transactions reverted",
            data: {
                reverted_amount: totalRevertedAmount,
                total_bids: allBids.length,
                winning_bids: winningBids.length,
                updated_bids: updateBidsResult.modifiedCount,
                deleted_wallet_transactions: deleteWalletTransactions.deletedCount,
                deleted_notifications: deleteNotificationsResult.deletedCount
            }
        });

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



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) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date } = req.body;
        const admin_id = req?.admin?._id

        if (!admin_id) {
            return res.status(400).json({ success: false, msg: "admin id not found" })
        }


        console.log("req.body of galidissawar result delete", req.body);

        // Use the result_dec_date from the frontend which is in proper ISO format
        const resultDate = new Date(result_dec_date);
        console.log("🚀 ~ deleteOpenGalidisswarResultData ~ 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
        const result = await gali_disswar_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: "Galidissawar game result not found for the specified date"
            });
        }

        // Check if close session is already processed (status = 0)
        if (result.close_decleare_status === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Close result is already deleted or not declared"
            });
        }

        // Get close result token
        const close_result_token = result.close_result_token;
        console.log("🚀 ~ deleteOpenGalidisswarResultData ~ close_result_token:", close_result_token);

        // Process refund for close session
        if (close_result_token && result.close_decleare_status === 1) {
            await processGalidissawarResultRefund({
                admin_id,
                result_token: close_result_token,
                session_type: 'close',
                gameDB_id,
                resultDate,
                mongooseSession: session
            });
        }

        // Delete user notifications for close session
        if (result.close_number) {
            await user_notification_module.deleteMany({
                msg: { $regex: result.close_number, $options: 'i' }
            }).session(session);
            console.log(`✅ Deleted notifications for close session with number: ${result.close_number}`);
        }

        // Delete the entire result document (since galidissawar has only one session)
        await gali_disswar_game_result_history_module.deleteOne({
            // _id: resultId,
            gameDB_id,
            result_date: resultDate
        }).session(session);
        console.log(`✅ Completely deleted galidissawar result document for ${resultDate}`);

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

        return res.status(200).json({
            success: true,
            message: "Deleted galidissawar close result successfully. Winning amounts deducted from user wallets. All bid statuses reset to 0.",
            data: {
                deletedSessions: ['close'],
                deleteType: 'close'
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("Error in deleteOpenGalidisswarResultData", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};
const processGalidissawarResultRefund = async ({ admin_id, result_token, session_type, gameDB_id, resultDate, mongooseSession }) => {
    console.log("🚀 ~ processGalidissawarResultRefund ~ result_token:", result_token)
    try {




        // Find all winning bids for this result token
        const winningBids = await gali_disswar_bid_history_module.find({
            close_result_token: result_token
        }).session(mongooseSession);

        console.log("🚀 ~ processGalidissawarResultRefund ~ 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({
                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 not, use available balance
                const actualDeductAmount = Math.min(refundAmount, userData.wallet_balance);
                console.log("🚀 ~ processGalidissawarResultRefund ~ userData:", userData, actualDeductAmount)

                if (actualDeductAmount > 0) {
                    // Generate unique transaction token
                    const refundTxToken = getUserRandomToken();


                    // Deduct amount from user wallet
                    await user_module.findByIdAndUpdate(
                        userDB_id,
                        { $inc: { wallet_balance: -actualDeductAmount } },
                        { new: true, session: mongooseSession }
                    );


                    await admin_module.findByIdAndUpdate(
                        admin_id,
                        { $inc: { wallet_amount: actualDeductAmount } },
                        { new: true, session: mongooseSession }
                    );



                    console.log(`✅ Successfully deducted ${actualDeductAmount} from user ${userDB_id}`);
                } else {
                    console.warn(`⚠️ User ${userDB_id} has insufficient balance for refund. Available: ${userData.wallet_balance}, Required: ${refundAmount}`);
                }
            }

            // Update bid pay_status to 0 (not paid)
            await gali_disswar_bid_history_module.updateOne(
                { _id: bid._id },
                {
                    $set: {
                        close_result_token: null,
                        pay_status: 0 // Reset payment status to not paid
                    }
                },
                { session: mongooseSession }
            );

            console.log(`✅ Updated bid ${bid._id} pay_status to 0`);
        }

        // Delete any remaining wallet transactions for this result token
        await wallet_trans_history_module.deleteMany({
            close_result_token: result_token
        }).session(mongooseSession);

        console.log(`✅ Deleted wallet transactions for ${session_type} result token: ${result_token}`);

    } catch (error) {
        console.error(`Error processing ${session_type} result refund:`, error);
        throw 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" })
    }

};

// main game bookie cutting group report
const cuttingGroupData = async (req, res) => {
    try {
        const {
            date = "",
            game = "",
            gameType = "",
            session = "",
            percent = "Optional"
        } = req?.body;

        if (!date || !game || !gameType || !session) {
            return res.status(400).json({ success: false, msg: "All fields are required" });
        }

        const timezone = "Asia/Kolkata";
        const searchDate = moment_timeZone.tz(date, "YYYY-MM-DD", timezone).startOf("day").toDate();
        const nextDate = moment_timeZone.tz(date, "YYYY-MM-DD", timezone).endOf("day").toDate();

        const baseQuery = {
            // gameDB_id: mongoose.Types.ObjectId.isValid(game)
            //     ? new mongoose.Types.ObjectId(game)
            //     : game,
            session: session,
            bid_date: { $gte: searchDate, $lte: nextDate }
        };

        if (game !== 'all') {
            if (mongoose.Types.ObjectId.isValid(game)) baseQuery.gameDB_id = new mongoose.Types.ObjectId(game);
            else res.status(400).json({ success: false, msg: "Invalid game ID" });
        }

        if (gameType !== "All") {
            baseQuery.pana = gameType;
        }

        const aggregationPipeline = [
            { $match: baseQuery },
            {
                $addFields: {
                    combinedDigit: {
                        $cond: {
                            if: {
                                $or: [
                                    { $eq: ["$pana", "Half Sangam"] },
                                    { $eq: ["$pana", "Full Sangam"] }
                                ]
                            },
                            then: {
                                $cond: {
                                    if: {
                                        $and: [
                                            { $ne: ["$closedigits", null] },
                                            { $ne: ["$closedigits", ""] }
                                        ]
                                    },
                                    then: { $concat: ["$digits", "-", "$closedigits"] },
                                    else: "$digits"
                                }
                            },
                            else: "$digits"
                        }
                    },
                    // For table rows: Show potential winning points (all winning_points)
                    potentialWinningPoints: "$winning_points",
                    // For summaries: Only actual winning points from pay_status = 1
                    actualWinningPoints: {
                        $cond: {
                            if: { $eq: ["$pay_status", 1] },
                            then: "$winning_points",
                            else: 0
                        }
                    }
                }
            },
            {
                $group: {
                    _id: { pana: "$pana", digit: "$combinedDigit" },
                    totalBids: { $sum: 1 },
                    totalPoints: { $sum: "$points" },
                    // For table rows: Show potential winning amount
                    totalPotentialWinningPoints: { $sum: "$potentialWinningPoints" },
                    // For summaries: Only actual winning amount from pay_status = 1
                    totalActualWinningPoints: { $sum: "$actualWinningPoints" },
                    wonBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 1] }, 1, 0]
                        }
                    },
                    lostBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 2] }, 1, 0]
                        }
                    },
                    pendingBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 0] }, 1, 0]
                        }
                    }
                }
            },
            {
                $addFields: {
                    // For table rows: Calculate potential profit/loss
                    potentialProfitLoss: {
                        $cond: {
                            if: { $gt: ["$totalBids", 0] }, // If bid placed
                            then: {
                                // Potential loss = totalPoints - totalPotentialWinningPoints
                                $subtract: ["$totalPoints", "$totalPotentialWinningPoints"]
                            },
                            else: 0 // No bid placed
                        }
                    },
                    // For summaries: Calculate actual profit/loss
                    actualProfitLoss: {
                        $cond: {
                            if: { $gt: ["$wonBidsCount", 0] }, // If any bid won
                            then: {
                                // Actual loss = totalPoints - totalActualWinningPoints
                                $subtract: ["$totalPoints", "$totalActualWinningPoints"]
                            },
                            else: {
                                // Profit = totalPoints (if lost or pending)
                                // "$totalPoints"
                            }
                        }
                    },
                    resultType: {
                        $cond: {
                            if: { $gt: ["$wonBidsCount", 0] },
                            then: "loss",
                            else: "profit"
                        }
                    }
                }
            },
            {
                $group: {
                    _id: "$_id.pana",
                    totalBids: { $sum: "$totalBids" },
                    totalPoints: { $sum: "$totalPoints" },
                    // For summaries: Only actual winning amounts
                    totalWinningPoints: { $sum: "$totalActualWinningPoints" },
                    totalProfit: { $sum: "$actualProfitLoss" },
                    totalWonBids: { $sum: "$wonBidsCount" },
                    digits: {
                        $push: {
                            digit: "$_id.digit",
                            bids: "$totalBids",
                            points: "$totalPoints",
                            // For table rows: Show potential winning amount
                            winning_points: "$totalPotentialWinningPoints",
                            potentialProfitLoss: "$potentialProfitLoss",
                            actualProfitLoss: "$actualProfitLoss",
                            resultType: "$resultType",
                            wonBidsCount: "$wonBidsCount",
                            lostBidsCount: "$lostBidsCount",
                            pendingBidsCount: "$pendingBidsCount"
                        }
                    }
                }
            },
            {
                $project: {
                    _id: 1,
                    totalBids: 1,
                    totalPoints: 1,
                    totalWinningPoints: 1,
                    totalProfit: 1,
                    totalWonBids: 1,
                    digits: 1
                }
            }
        ];

        const groupedData = await bid_history_module.aggregate(aggregationPipeline);

        // 🧮 Generate all possible digits for each game type
        const enhancedGroupedData = groupedData.map(group => {
            let allDigits = [];

            if (group._id === "Single Digit") {
                // Generate digits 0-9
                for (let i = 0; i <= 9; i++) {
                    const existingDigit = group.digits.find(d => d.digit === i.toString());
                    if (existingDigit) {
                        // Bid placed - show potential winning amount and potential loss
                        allDigits.push(existingDigit);
                    } else {
                        // No bid placed - show profit with default amount
                        const defaultPoints = 10; // Default bid amount
                        allDigits.push({
                            digit: i.toString(),
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints, // Show profit for no bids
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                }
            } else {
                // For other game types, show only digits with bids
                allDigits = group.digits;
            }

            return {
                ...group,
                digits: allDigits
            };
        });

        // 🧮 Calculate overall summary (only includes actual winning amounts from pay_status = 1)
        const overallSummary = enhancedGroupedData.reduce(
            (acc, group) => {
                acc.totalBids += group.totalBids;
                acc.totalAmount += group.totalPoints;
                acc.winningAmount += group.totalWinningPoints; // Only actual winning amounts
                acc.totalProfit += group.totalProfit; // Only actual profit/loss
                return acc;
            },
            {
                totalAmount: 0,
                totalBids: 0,
                winningAmount: 0,
                totalProfit: 0
            }
        );

        return res.status(200).json({
            success: true,
            data: {
                groupedData: enhancedGroupedData,
                overallSummary
            }
        });
    } catch (err) {
        console.log("error in cuttingGroupData", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error",
            error: err.message
        });
    }
};

// main game bid details with user info
const getBidDetails = async (req, res) => {
    try {
        const {
            date = "",
            game = "",
            gameType = "",
            session = "",
            digit = "",
            percent = "Optional"
        } = req?.body;

        console.log("🚀 ~ getBidDetails ~ req?.body:", req?.body);

        if (!date || !game || !gameType || !session || !digit) {
            return res.status(400).json({
                success: false,
                msg: "All fields including digit are required"
            });
        }

        const timezone = 'Asia/Kolkata';

        // Parse the input date properly
        const searchDate = moment_timeZone.tz(date, 'YYYY-MM-DD', timezone).startOf('day').toDate();
        const nextDate = moment_timeZone.tz(date, 'YYYY-MM-DD', timezone).endOf('day').toDate();

        console.log("Searching for bid details with date range:", searchDate, "to", nextDate);
        console.log("Searching for digit:", digit, "in game type:", gameType);

        // Build base query
        let baseQuery = {
            gameDB_id: mongoose.Types.ObjectId.isValid(game) ? new mongoose.Types.ObjectId(game) : game,
            session: session,
            bid_date: {
                $gte: searchDate,
                $lte: nextDate
            },
            pana: gameType
        };

        // Handle digit matching based on game type and combined digits for Half/Full Sangam
        if (gameType === "Half Sangam" || gameType === "Full Sangam") {
            // For Half/Full Sangam, check if digit contains hyphen (combined format)
            if (digit.includes('-')) {
                const [openPart, closePart] = digit.split('-');
                baseQuery.digits = openPart;
                baseQuery.closedigits = closePart;
            } else {
                // Fallback: search in digits field
                baseQuery.digits = digit;
            }
        } else {
            // For other game types, search directly in digits field
            baseQuery.digits = digit;
        }

        console.log("Bid details query:", JSON.stringify(baseQuery, null, 2));

        // Fetch bid details with user information
        const bidDetails = await bid_history_module.aggregate([
            {
                $match: baseQuery
            },
            {
                $lookup: {
                    from: "users", // Assuming your users collection name
                    localField: "userDB_id",
                    foreignField: "_id",
                    as: "userInfo"
                }
            },
            {
                $unwind: {
                    path: "$userInfo",
                    preserveNullAndEmptyArrays: true // Include bids even if user not found
                }
            },
            {
                $project: {
                    bid_tx_id: 1,
                    points: 1,
                    winning_points: 1,
                    status: 1,
                    pay_status: 1,
                    bid_date: 1,
                    insert_date: 1,
                    pana: 1,
                    digits: 1,
                    closedigits: 1,
                    session: 1,
                    "userInfo.user_name": 1,
                    "userInfo.mobile": 1,
                    "userInfo._id": 1
                }
            },
            {
                $sort: {
                    bid_date: -1 // Sort by most recent first
                }
            }
        ]);

        console.log(`Found ${bidDetails.length} bid details for digit ${digit}`);

        // Format the response data
        const formattedBids = bidDetails.map(bid => ({
            bid_tx_id: bid.bid_tx_id,
            user_name: bid.userInfo?.user_name || "Unknown User",
            user_mobile: bid.userInfo?.mobile || "N/A",
            user_id: bid.userInfo?._id || "N/A",
            points: bid.points || 0,
            winning_points: bid.winning_points || 0,
            status: bid.status || 0,
            pay_status: bid.pay_status || 0,
            bid_date: bid.bid_date,
            insert_date: bid?.insert_date,
            pana: bid.pana,
            digit: bid.digits,
            closedigits: bid.closedigits || "",
            session: bid.session
        }));

        return res.status(200).json({
            success: true,
            data: {
                bids: formattedBids,
                summary: {
                    totalBids: bidDetails.length,
                    totalPoints: bidDetails.reduce((sum, bid) => sum + (bid.points || 0), 0),
                    totalWinningPoints: bidDetails.reduce((sum, bid) => sum + (bid.winning_points || 0), 0),
                    searchDigit: digit,
                    gameType: gameType,
                    session: session,
                    date: date
                }
            }
        });

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


// galidisswar/ jackpot game bookie cutting group report
const galiDissawarCuttingGroupData = async (req, res) => {
    try {
        const {
            date = "",
            game = "",
            gameType = "",
            session = "",
            percent = "Optional"
        } = req?.body;

        if (!date || !game || !gameType || !session) {
            return res.status(400).json({ success: false, msg: "All fields are required" });
        }

        const timezone = "Asia/Kolkata";
        const searchDate = moment_timeZone.tz(date, "YYYY-MM-DD", timezone).startOf("day").toDate();
        const nextDate = moment_timeZone.tz(date, "YYYY-MM-DD", timezone).endOf("day").toDate();

        const baseQuery = {
            session: session,
            bid_date: { $gte: searchDate, $lte: nextDate }
        };

        if (game !== 'all') {
            if (mongoose.Types.ObjectId.isValid(game)) baseQuery.gameDB_id = new mongoose.Types.ObjectId(game);
            else return res.status(400).json({ success: false, msg: "Invalid game ID" });
        }

        if (gameType !== "All") {
            baseQuery.pana = gameType;
        }

        const aggregationPipeline = [
            { $match: baseQuery },
            {
                $addFields: {
                    // For Gali Dissawar, we don't need combinedDigit like Sangam
                    combinedDigit: "$digits",
                    // For table rows: Show potential winning points (all winning_points)
                    potentialWinningPoints: "$winning_points",
                    // For summaries: Only actual winning points from pay_status = 1
                    actualWinningPoints: {
                        $cond: {
                            if: { $eq: ["$pay_status", 1] },
                            then: "$winning_points",
                            else: 0
                        }
                    }
                }
            },
            {
                $group: {
                    _id: { pana: "$pana", digit: "$combinedDigit" },
                    totalBids: { $sum: 1 },
                    totalPoints: { $sum: "$points" },
                    // For table rows: Show potential winning amount
                    totalPotentialWinningPoints: { $sum: "$potentialWinningPoints" },
                    // For summaries: Only actual winning amount from pay_status = 1
                    totalActualWinningPoints: { $sum: "$actualWinningPoints" },
                    wonBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 1] }, 1, 0]
                        }
                    },
                    lostBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 2] }, 1, 0]
                        }
                    },
                    pendingBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 0] }, 1, 0]
                        }
                    }
                }
            },
            {
                $addFields: {
                    // For table rows: Calculate potential profit/loss
                    potentialProfitLoss: {
                        $cond: {
                            if: { $gt: ["$totalBids", 0] }, // If bid placed
                            then: {
                                // Potential loss = totalPoints - totalPotentialWinningPoints
                                $subtract: ["$totalPoints", "$totalPotentialWinningPoints"]
                            },
                            else: 0 // No bid placed
                        }
                    },
                    // For summaries: Calculate actual profit/loss
                    actualProfitLoss: {
                        $cond: {
                            if: { $gt: ["$wonBidsCount", 0] }, // If any bid won
                            then: {
                                // Actual loss = totalPoints - totalActualWinningPoints
                                $subtract: ["$totalPoints", "$totalActualWinningPoints"]
                            },
                            else: "$totalPoints" // Profit = totalPoints (if lost or pending)
                        }
                    },
                    resultType: {
                        $cond: {
                            if: { $gt: ["$wonBidsCount", 0] },
                            then: "loss",
                            else: "profit"
                        }
                    }
                }
            },
            {
                $group: {
                    _id: "$_id.pana",
                    totalBids: { $sum: "$totalBids" },
                    totalPoints: { $sum: "$totalPoints" },
                    // For summaries: Only actual winning amounts
                    totalWinningPoints: { $sum: "$totalActualWinningPoints" },
                    totalProfit: { $sum: "$actualProfitLoss" },
                    totalWonBids: { $sum: "$wonBidsCount" },
                    digits: {
                        $push: {
                            digit: "$_id.digit",
                            bids: "$totalBids",
                            points: "$totalPoints",
                            // For table rows: Show potential winning amount
                            winning_points: "$totalPotentialWinningPoints",
                            potentialProfitLoss: "$potentialProfitLoss",
                            actualProfitLoss: "$actualProfitLoss",
                            resultType: "$resultType",
                            wonBidsCount: "$wonBidsCount",
                            lostBidsCount: "$lostBidsCount",
                            pendingBidsCount: "$pendingBidsCount"
                        }
                    }
                }
            },
            {
                $project: {
                    _id: 1,
                    totalBids: 1,
                    totalPoints: 1,
                    totalWinningPoints: 1,
                    totalProfit: 1,
                    totalWonBids: 1,
                    digits: 1
                }
            }
        ];

        const groupedData = await gali_disswar_bid_history_module.aggregate(aggregationPipeline);

        // 🧮 Generate all possible digits for each Gali Dissawar game type
        const enhancedGroupedData = groupedData.map(group => {
            let allDigits = [];
            const defaultPoints = 10; // Default bid amount for profit calculation

            if (group._id === "Jodi Digit") {
                // Generate all possible Jodi digits (00-99)
                for (let i = 0; i <= 99; i++) {
                    const digitStr = i.toString().padStart(2, '0');
                    const existingDigit = group.digits.find(d => d.digit === digitStr);
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        // No bid placed - show profit with default amount
                        allDigits.push({
                            digit: digitStr,
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                }
            } else if (group._id === "Group Jodi") {
                // Group Jodi typically uses the same 00-99 digits
                for (let i = 0; i <= 99; i++) {
                    const digitStr = i.toString().padStart(2, '0');
                    const existingDigit = group.digits.find(d => d.digit === digitStr);
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        allDigits.push({
                            digit: digitStr,
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                }
            } else if (group._id === "Red Bracket") {
                // Red Bracket also uses 00-99 digits
                for (let i = 0; i <= 99; i++) {
                    const digitStr = i.toString().padStart(2, '0');
                    const existingDigit = group.digits.find(d => d.digit === digitStr);
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        allDigits.push({
                            digit: digitStr,
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                }
            } else {
                // For any other game types, show only digits with bids
                allDigits = group.digits;
            }

            return {
                ...group,
                digits: allDigits
            };
        });

        // 🧮 Calculate overall summary (only includes actual winning amounts from pay_status = 1)
        const overallSummary = enhancedGroupedData.reduce(
            (acc, group) => {
                acc.totalBids += group.totalBids;
                acc.totalAmount += group.totalPoints;
                acc.winningAmount += group.totalWinningPoints; // Only actual winning amounts
                acc.totalProfit += group.totalProfit; // Only actual profit/loss
                return acc;
            },
            {
                totalAmount: 0,
                totalBids: 0,
                winningAmount: 0,
                totalProfit: 0
            }
        );

        return res.status(200).json({
            success: true,
            data: {
                groupedData: enhancedGroupedData,
                overallSummary
            }
        });
    } catch (err) {
        console.log("error in galiDissawarCuttingGroupData", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error",
            error: err.message
        });
    }
};

// gali disswar/ jackpot game bid details report // view bids
const getGaliDissawarBidDetails = async (req, res) => {
    try {
        const {
            date = "",
            game = "",
            gameType = "",
            session = "Close",
            digit = "",
            percent = "Optional",
            accessing = ""
        } = req?.body;

        if (!date || !game || !gameType || !session || !digit) {
            return res.status(400).json({ success: false, msg: "All fields are required" });
        }

        const timezone = "Asia/Kolkata";
        const searchDate = moment_timeZone.tz(date, "YYYY-MM-DD", timezone).startOf("day").toDate();
        const nextDate = moment_timeZone.tz(date, "YYYY-MM-DD", timezone).endOf("day").toDate();

        const baseQuery = {
            session: session,
            pana: gameType,
            digits: digit,
            bid_date: { $gte: searchDate, $lte: nextDate }
        };

        if (game !== 'all') {
            if (mongoose.Types.ObjectId.isValid(game)) {
                baseQuery.gameDB_id = new mongoose.Types.ObjectId(game);
            } else {
                return res.status(400).json({ success: false, msg: "Invalid game ID" });
            }
        }

        const bids = await gali_disswar_bid_history_module.find(baseQuery)
            .populate('userDB_id', 'user_name mobile_number')
            .select('bid_tx_id userDB_id points winning_points status pay_status insert_date')
            .sort({ insert_date: -1 });

        // Format the response
        const formattedBids = bids.map(bid => ({
            bid_tx_id: bid.bid_tx_id,
            user_name: bid.userDB_id?.user_name || "N/A",
            points: bid.points,
            winning_points: bid.winning_points,
            status: bid.status,
            pay_status: bid.pay_status,
            insert_date: bid.insert_date
        }));

        return res.status(200).json({
            success: true,
            data: {
                bids: formattedBids,
                totalBids: formattedBids.length
            },
            msg: "Bid details fetched successfully"
        });
    } catch (err) {
        console.log("error in getGaliDissawarBidDetails", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error",
            error: err.message
        });
    }
};



// starline bookie cutting group report
const starlineCuttingGroupData = async (req, res) => {
    try {
        const {
            startDate: date,  // Changed from startDate to date
            gameDB_id = "",
            gameType = "",
            percent = "Optional"
        } = req?.body;

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

        const timezone = "Asia/Kolkata";
        const searchDate = moment_timeZone.tz(date, "Asia/Kolkata").startOf("day").toDate();
        const nextDate = moment_timeZone.tz(date, "Asia/Kolkata").endOf("day").toDate();

        const baseQuery = {
            bid_date: { $gte: searchDate, $lte: nextDate }
        };

        console.log("🚀 ~ starlineCuttingGroupData ~ baseQuery:", baseQuery)

        if (gameDB_id !== 'all') {
            if (mongoose.Types.ObjectId.isValid(gameDB_id)) {
                baseQuery.gameDB_id = new mongoose.Types.ObjectId(gameDB_id);
            } else {
                return res.status(400).json({ success: false, msg: "Invalid game ID" });
            }
        }

        if (gameType !== "All") {
            baseQuery.pana = gameType;
        }

        const aggregationPipeline = [
            { $match: baseQuery },
            {
                $addFields: {
                    combinedDigit: "$digits",
                    potentialWinningPoints: "$winning_points",
                    actualWinningPoints: {
                        $cond: {
                            if: { $eq: ["$pay_status", 1] },
                            then: "$winning_points",
                            else: 0
                        }
                    }
                }
            },
            {
                $group: {
                    _id: { pana: "$pana", digit: "$combinedDigit" },
                    totalBids: { $sum: 1 },
                    totalPoints: { $sum: "$points" },
                    totalPotentialWinningPoints: { $sum: "$potentialWinningPoints" },
                    totalActualWinningPoints: { $sum: "$actualWinningPoints" },
                    wonBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 1] }, 1, 0]
                        }
                    },
                    lostBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 2] }, 1, 0]
                        }
                    },
                    pendingBidsCount: {
                        $sum: {
                            $cond: [{ $eq: ["$pay_status", 0] }, 1, 0]
                        }
                    }
                }
            },
            {
                $addFields: {
                    potentialProfitLoss: {
                        $cond: {
                            if: { $gt: ["$totalBids", 0] },
                            then: {
                                $subtract: ["$totalPoints", "$totalPotentialWinningPoints"]
                            },
                            else: 0
                        }
                    },
                    actualProfitLoss: {
                        $cond: {
                            if: { $gt: ["$wonBidsCount", 0] },
                            then: {
                                $subtract: ["$totalPoints", "$totalActualWinningPoints"]
                            },
                            else: "$totalPoints"
                        }
                    },
                    resultType: {
                        $cond: {
                            if: { $gt: ["$wonBidsCount", 0] },
                            then: "loss",
                            else: "profit"
                        }
                    }
                }
            },
            {
                $group: {
                    _id: "$_id.pana",
                    totalBids: { $sum: "$totalBids" },
                    totalPoints: { $sum: "$totalPoints" },
                    totalWinningPoints: { $sum: "$totalActualWinningPoints" },
                    totalProfit: { $sum: "$actualProfitLoss" },
                    totalWonBids: { $sum: "$wonBidsCount" },
                    digits: {
                        $push: {
                            digit: "$_id.digit",
                            bids: "$totalBids",
                            points: "$totalPoints",
                            winning_points: "$totalPotentialWinningPoints",
                            potentialProfitLoss: "$potentialProfitLoss",
                            actualProfitLoss: "$actualProfitLoss",
                            resultType: "$resultType",
                            wonBidsCount: "$wonBidsCount",
                            lostBidsCount: "$lostBidsCount",
                            pendingBidsCount: "$pendingBidsCount"
                        }
                    }
                }
            },
            {
                $project: {
                    _id: 1,
                    totalBids: 1,
                    totalPoints: 1,
                    totalWinningPoints: 1,
                    totalProfit: 1,
                    totalWonBids: 1,
                    digits: 1
                }
            }
        ];

        const groupedData = await starline_bid_history_module.aggregate(aggregationPipeline);

        // Generate all possible digits for each Starline game type
        const enhancedGroupedData = groupedData.map(group => {
            let allDigits = [];
            const defaultPoints = 10;

            if (group._id === "Single Digit") {
                // Generate digits 0-9
                for (let i = 0; i <= 9; i++) {
                    const existingDigit = group.digits.find(d => d.digit === i.toString());
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        allDigits.push({
                            digit: i.toString(),
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                }
            } else if (group._id === "Single Pana") {
                // Generate all single pana digits (all unique 3-digit combinations)
                const singlePanaDigits = [];
                for (let i = 0; i <= 9; i++) {
                    for (let j = 0; j <= 9; j++) {
                        for (let k = 0; k <= 9; k++) {
                            if (i !== j && i !== k && j !== k) {
                                singlePanaDigits.push(`${i}${j}${k}`);
                            }
                        }
                    }
                }

                singlePanaDigits.forEach(digitStr => {
                    const existingDigit = group.digits.find(d => d.digit === digitStr);
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        allDigits.push({
                            digit: digitStr,
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                });
            } else if (group._id === "Double Pana") {
                // Generate all double pana digits
                const doublePanaDigits = [];
                for (let i = 0; i <= 9; i++) {
                    for (let j = 0; j <= 9; j++) {
                        if (i !== j) {
                            doublePanaDigits.push(`${i}${i}${j}`);
                            doublePanaDigits.push(`${i}${j}${i}`);
                            doublePanaDigits.push(`${j}${i}${i}`);
                        }
                    }
                }

                doublePanaDigits.forEach(digitStr => {
                    const existingDigit = group.digits.find(d => d.digit === digitStr);
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        allDigits.push({
                            digit: digitStr,
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                });
            } else if (group._id === "Triple Pana") {
                // Generate all triple pana digits (000-999)
                for (let i = 0; i <= 9; i++) {
                    const digitStr = i.toString().repeat(3);
                    const existingDigit = group.digits.find(d => d.digit === digitStr);
                    if (existingDigit) {
                        allDigits.push(existingDigit);
                    } else {
                        allDigits.push({
                            digit: digitStr,
                            bids: 0,
                            points: 0,
                            winning_points: 0,
                            potentialProfitLoss: defaultPoints,
                            actualProfitLoss: defaultPoints,
                            resultType: "profit",
                            wonBidsCount: 0,
                            lostBidsCount: 0,
                            pendingBidsCount: 0
                        });
                    }
                }
            } else {
                // For any other game types, show only digits with bids
                allDigits = group.digits;
            }

            return {
                ...group,
                digits: allDigits
            };
        });

        // Calculate overall summary
        const overallSummary = enhancedGroupedData.reduce(
            (acc, group) => {
                acc.totalBids += group.totalBids;
                acc.totalAmount += group.totalPoints;
                acc.winningAmount += group.totalWinningPoints;
                acc.totalProfit += group.totalProfit;
                return acc;
            },
            {
                totalAmount: 0,
                totalBids: 0,
                winningAmount: 0,
                totalProfit: 0
            }
        );

        return res.status(200).json({
            success: true,
            data: {
                groupedData: enhancedGroupedData,
                overallSummary
            }
        });
    } catch (err) {
        console.log("error in starlineCuttingGroupData", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error",
            error: err.message
        });
    }
};


// starline game bid details report // view bids

const getStarlineBidDetails = async (req, res) => {
    try {
        const {
            startDate = "",
            gameDB_id = "",
            gameType = "",
            digit = "",
            percent = "Optional",
            accessing = ""
        } = req?.body;

        if (!startDate || !gameDB_id || !gameType || !digit) {
            return res.status(400).json({ success: false, msg: "All fields are required" });
        }

        const timezone = "Asia/Kolkata";
        const searchDate = moment_timeZone.tz(startDate, "Asia/Kolkata").startOf("day").toDate();
        const nextDate = moment_timeZone.tz(startDate, "Asia/Kolkata").endOf("day").toDate();

        const baseQuery = {
            pana: gameType,
            digits: digit,
            bid_date: { $gte: searchDate, $lte: nextDate }
        };

        if (gameDB_id !== 'all') {
            if (mongoose.Types.ObjectId.isValid(gameDB_id)) {
                baseQuery.gameDB_id = new mongoose.Types.ObjectId(gameDB_id);
            } else {
                return res.status(400).json({ success: false, msg: "Invalid game ID" });
            }
        }

        const bids = await starline_bid_history_module.find(baseQuery)
            .populate('userDB_id', 'user_name mobile')
            .select('bid_tx_id userDB_id points winning_points status pay_status insert_date')
            .sort({ insert_date: -1 });

        // Format the response
        const formattedBids = bids.map(bid => ({
            bid_tx_id: bid.bid_tx_id,
            user_name: bid.userDB_id?.user_name || "N/A",
            points: bid.points,
            winning_points: bid.winning_points,
            status: bid.status,
            pay_status: bid.pay_status,
            insert_date: bid.insert_date
        }));

        return res.status(200).json({
            success: true,
            data: {
                bids: formattedBids,
                totalBids: formattedBids.length
            },
            msg: "Starline bid details fetched successfully"
        });
    } catch (err) {
        console.log("error in getStarlineBidDetails", err);
        return res.status(500).json({
            success: false,
            msg: "Internal Server Error",
            error: err.message
        });
    }
};




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 { 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", [4, 6, 7, 8, 9, 19]] }, // removed 1 status to don't count admin added funds
                                then: "$amount",
                                else: 0
                            }
                        }
                    },
                    totalWithdrawal: {
                        $sum: {
                            $cond: {
                                if: { $in: ["$amount_status", [3, 5, 10]] }, // removed 2 status to don't count admin withdrawals
                                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, openDigitValueForJodi } = 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
        };

        // Helper: Sum digits of a number (Pana) and return %10
        function sumDigitsMod10(num) {
            if (!num) return null;
            const digits = num.toString().split('').map(d => parseInt(d));
            const total = digits.reduce((sum, d) => sum + d, 0);
            return total % 10;
        }


        // Handle session and digit filtering
        if (openDigit) {
            console.log("found open digit");
            filter.$or = [
                { digits: `${sumDigitsMod10(openDigit) % 10}` },
                { digits: `${openDigit}` }
            ],
                filter.session = "Open";
        }

        if (closeDigit) {
            console.log("found close digit");

            const openSum = sumDigitsMod10(openDigitValueForJodi);
            const closeSum = sumDigitsMod10(closeDigit);

            // Construct digit keys
            const closeSingleDigit = `${closeSum}`;
            const jodiDigit = `${openSum}${closeSum}`;

            console.log("🚀 ~ Close single:", closeSingleDigit, "Jodi:", jodiDigit);

            // Apply OR condition inside MongoDB query
            filter.$or = [
                { digits: closeSingleDigit, pana: "Single Digit" }, // Close single match
                { digits: jodiDigit, pana: "Jodi Digit" },         // Jodi match

                { digits: closeDigit, pana: "Single Pana" },         // single pana match
                { digits: closeDigit, pana: "Double Pana" },         // double pana match
                { digits: closeDigit, pana: "Triple Pana" },         // triple pana match

                { digits: closeSingleDigit, closedigits: closeDigit, pana: "Half Sangam" },   // half sangam A
                { digits: closeDigit, closedigits: closeSingleDigit, pana: "Half Sangam" },   // half sangam B
                { digits: openDigitValueForJodi, closedigits: closeDigit, pana: "Full Sangam" } // full sangam
            ];

            filter.session = "Close";
        }



        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 fetchGalidissawarGameResultHistory = async (req, res) => {
    try {
        const { gameDb_id, bid_date, closeDigit } = req?.body;

        console.log("Galidissawar req?.body ", req?.body);

        if (!gameDb_id || !bid_date || !closeDigit) {
            return res.status(404).json({ success: false, msg: "gameId, bid_Date and closeDigit not found !" });
        }

        let filter = {
            pay_status: 1,
            gameDB_id: new ObjectId(gameDb_id)
        };

        // Helper: Sum digits of a number (Pana) and return %10
        function sumDigitsMod10(num) {
            if (!num) return null;
            const digits = num.toString().split('').map(d => parseInt(d));
            const total = digits.reduce((sum, d) => sum + d, 0);
            return total % 10;
        }

        // Handle close digit filtering for galidissawar
        if (closeDigit) {
            console.log("found close digit for galidissawar");

            const closeSum = sumDigitsMod10(closeDigit);
            const closeSingleDigit = `${closeSum}`;

            console.log("🚀 ~ Galidissawar Close single digit:", closeSingleDigit);

            // For galidissawar, only match the single close digit
            // filter.digits = closeSingleDigit;
            filter.digits = closeDigit; // checking with original closeDigit value
            filter.session = "Close";
        }

        if (bid_date) {
            const startDate = moment_timeZone.tz(bid_date, "Asia/Kolkata").startOf('day');
            const endDate = startDate.clone().endOf('day');

            console.log("Galidissawar 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("Galidissawar Final filter:", JSON.stringify(filter, null, 2));

        let withdrawRequestData = await gali_disswar_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,
                    points: 1,
                    bid_tx_id: 1,
                    status: 1,
                    pay_status: 1,
                    bid_date: 1,
                    insert_date: 1,
                    close_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("Galidissawar records found:", withdrawRequestData.length);
        if (withdrawRequestData.length > 0) {
            console.log("Galidissawar sample record:", withdrawRequestData[0]);
        }

        return res.status(200).json({
            success: true,
            msg: "Galidissawar data fetched successfully",
            data: withdrawRequestData
        });

    } catch (err) {
        console.error("Error in fetchGalidissawarGameResultHistory:", err);
        return res.status(500).json({
            success: false,
            msg: "Internal server error"
        });
    }
};
const revertGalidissawarBids = async (req, res) => {
    const session = await mongoose.startSession();
    session.startTransaction();

    try {
        const { gameDB_id, result_dec_date, resultId } = req.body;

        console.log("🚀 ~ revertGalidissawarBids ~ 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"
            });
        }

        // Parse the date for range filtering
        const istDate = moment_timeZone.tz(result_dec_date, "Asia/Kolkata");
        const startDate = istDate.clone().startOf('day').toDate();
        const endDate = istDate.clone().endOf('day').toDate();
        console.log("Galidissawar date range for bids:", { startDate, endDate });

        // Step 1: Find the galidissawar game result
        const resultDate = new Date(result_dec_date);
        const gameResult = await gali_disswar_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: "Galidissawar game result not found"
            });
        }

        const close_result_token = gameResult.close_result_token;

        console.log("🔍 Found galidissawar game result with token:", { close_result_token });

        // Check if close session is declared
        if (!close_result_token || gameResult.close_decleare_status !== 1) {
            await session.abortTransaction();
            session.endSession();
            return res.status(400).json({
                success: false,
                message: "Close result is not declared yet"
            });
        }

        // Build the query with date range
        const query = {
            close_result_token: close_result_token,
            gameDB_id: gameDB_id,
            bid_date: {
                $gte: startDate,
                $lte: endDate
            }
        };

        console.log("🔍 Galidissawar query for bids:", JSON.stringify(query, null, 2));

        // Find ALL bids associated with declared result token
        const allBids = await gali_disswar_bid_history_module.find(query).session(session);

        // return res.status(200).json({
        //     success: true,
        //     message: `Found ${allBids.length} galidissawar bids for declared session`,
        //     data: allBids
        // });

        console.log(`🔍 Found ${allBids.length} galidissawar bids to revert`);

        if (allBids.length === 0) {
            await session.abortTransaction();
            session.endSession();
            return res.status(404).json({
                success: false,
                message: "No bids found for declared session in this game result"
            });
        }

        let totalRefundedAmount = 0;
        let revertedBidsCount = 0;
        let totalBidAmount = 0;
        let totalWinningAmount = 0;

        if (!req?.admin) {

            await session.abortTransaction();
            session.endSession();
            return res.status(403).json({
                success: false,
                message: "Unauthorized: Admin credentials required"
            });
        }
        const admin_id = req?.admin?._id;

        // Step 2: Process each bid individually
        for (const bid of allBids) {
            try {
                console.log("🚀 ~ revertGalidissawarBids ~ bid:", bid)


                const refundResult = await processSingleGalidissawarBidRevert({
                    bid,
                    session,
                    admin_id
                });

                totalRefundedAmount += refundResult.refundAmount;
                totalBidAmount += refundResult.bidAmount;
                totalWinningAmount += refundResult.winningAmount;
                revertedBidsCount++;

                console.log(`✅ Successfully reverted galidissawar bid: ${bid.bid_tx_id}, refunded: ${refundResult.refundAmount}`);
            } catch (bidError) {
                console.error(`❌ Failed to revert galidissawar bid ${bid.bid_tx_id}:`, bidError);
                // Continue with other bids even if one fails
            }
        }

        // Step 3: Delete the galidissawar game result document
        await gali_disswar_game_result_history_module.deleteOne({
            _id: resultId,
            gameDB_id: gameDB_id,
            result_date: resultDate
        }).session(session);
        console.log(`🗑️ Deleted complete galidissawar game result: ${resultId}`);

        // Step 4: Delete user notifications for close session
        if (gameResult.close_number) {
            await user_notification_module.deleteMany({
                msg: { $regex: gameResult.close_number, $options: 'i' }
            }).session(session);
            console.log(`🗑️ Deleted related notifications for close number: ${gameResult.close_number}`);
        }

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

        return res.status(200).json({
            success: true,
            message: `Successfully reverted ${revertedBidsCount} galidissawar bids for close session. Total refunded: ${totalRefundedAmount} points.`,
            data: {
                revertedBidsCount,
                totalRefundedAmount,
                totalBidAmount,
                totalWinningAmount,
                revertType: 'close',
                deletedResult: resultId
            }
        });

    } catch (error) {
        await session.abortTransaction();
        session.endSession();
        console.log("❌ Error in revertGalidissawarBids", error);
        return res.status(500).json({
            success: false,
            message: error.message
        });
    }
};

// Helper function to process single galidissawar bid revert
const processSingleGalidissawarBidRevert = async ({ bid, session, admin_id }) => {
    try {
        const userDB_id = bid.userDB_id;
        const bid_tx_id = bid.bid_tx_id;

        console.log(`🔄 Processing galidissawar 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(`💰 Galidissawar 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 = `Galidissawar 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 = `Galidissawar 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 }
                );

                await admin_module.findByIdAndUpdate(
                    admin_id,
                    { $inc: { wallet_amount: - 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 }
                );

                await admin_module.findByIdAndUpdate(
                    admin_id,
                    { $inc: { wallet_amount: 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 gali_disswar_bid_history_module.deleteOne({
            bid_tx_id: bid_tx_id,
            userDB_id: userDB_id
        }).session(session);

        console.log(`🗑️ Deleted galidissawar bid: ${bid_tx_id}`);

        return {
            refundAmount: netAdjustment > 0 ? netAdjustment : 0,
            deductionAmount: netAdjustment < 0 ? Math.abs(netAdjustment) : 0,
            netAdjustment: netAdjustment,
            bidAmount: bidPoints,
            winningAmount: winningPoints
        };

    } catch (error) {
        console.error(`❌ Error in processSingleGalidissawarBidRevert:`, error);
        throw error;
    }
};

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

        console.log("🚀 ~ OcCuttingData ~ req.body:", req.body);

        const matchConditions = {};

        if (date) {
            // Convert to the correct timezone (example: Asia/Kolkata)
            const timezone = "Asia/Kolkata";

            const startDate = moment_timeZone.tz(date, timezone).startOf("day").toDate();
            const endDate = moment_timeZone.tz(date, timezone).endOf("day").toDate();

            matchConditions.bid_date = {
                $gte: startDate,
                $lte: endDate
            };
            console.log("🚀 ~ OcCuttingData ~ matchConditions:", matchConditions)
        }

        if (gameDB_id && gameDB_id !== 'all' && gameDB_id !== 'Select an option') {
            matchConditions.gameDB_id = gameDB_id;
        }

        if (session && session !== 'all' && session !== 'Select Session') {
            matchConditions.session = session;
        }

        console.log("Match conditions:", JSON.stringify(matchConditions, null, 2));

        // Get all matching records
        const allRecords = await bid_history_module.find(matchConditions);
        console.log(`Found ${allRecords.length} total records`);

        // Initialize categorized data with ALL possible digits for each game type
        const categorizedData = {
            singleDigit: {},
            jodiDigit: {},
            singlePana: {},
            doublePana: {},
            triplePana: {},
            halfSangam: {},
            fullSangam: {}
        };

        // Generate and initialize all possible digits with 0
        // Single Digit: 0-9
        for (let i = 0; i <= 9; i++) {
            categorizedData.singleDigit[i.toString()] = 0;
        }

        // Jodi Digit: 00-99
        for (let i = 0; i <= 99; i++) {
            const digit = i.toString().padStart(2, '0');
            categorizedData.jodiDigit[digit] = 0;
        }

        // Single Pana: All 3-digit combinations with unique digits (permutations: 10*9*8 = 720)
        for (let i = 0; i <= 9; i++) {
            for (let j = 0; j <= 9; j++) {
                if (j === i) continue;
                for (let k = 0; k <= 9; k++) {
                    if (k === i || k === j) continue;
                    const digit = `${i}${j}${k}`;
                    categorizedData.singlePana[digit] = 0;
                }
            }
        }

        // Double Pana: All 3-digit with exactly two same digits (270 possibilities)
        for (let i = 0; i <= 9; i++) {
            for (let j = 0; j <= 9; j++) {
                if (i === j) continue;
                // i i j
                categorizedData.doublePana[`${i}${i}${j}`] = 0;
                // i j i
                categorizedData.doublePana[`${i}${j}${i}`] = 0;
                // j i i
                categorizedData.doublePana[`${j}${i}${i}`] = 0;
            }
        }

        // Triple Pana: 000, 111, ..., 999
        for (let i = 0; i <= 9; i++) {
            const digit = i.toString().repeat(3);
            categorizedData.triplePana[digit] = 0;
        }

        // For Half Sangam and Full Sangam: Initialize only with actual digits found in records (as they are variable combinations)
        // We'll collect them during processing

        // Process each record and categorize/add points
        allRecords.forEach(record => {
            const digit = record.digits;
            const closedigits = record.closedigits || '';  // Define closedigits from record
            const points = record.points || 0;
            const pana = record.pana;

            // Categorize based on pana type and digit pattern
            switch (pana) {
                case 'Single Digit':
                    if (categorizedData.singleDigit[digit] !== undefined) {
                        categorizedData.singleDigit[digit] += points;
                    }
                    break;

                case 'Jodi Digit':
                    if (categorizedData.jodiDigit[digit] !== undefined) {
                        categorizedData.jodiDigit[digit] += points;
                    }
                    break;

                case 'Single Pana':
                    // Validate it's a valid single pana (3 unique digits)
                    if (/^\d{3}$/.test(digit)) {
                        const digitsArr = digit.split('');
                        const uniqueDigits = new Set(digitsArr);
                        if (uniqueDigits.size === 3) {
                            if (categorizedData.singlePana[digit] !== undefined) {
                                categorizedData.singlePana[digit] += points;
                            }
                        }
                    }
                    break;

                case 'Double Pana':
                    // Validate it's a valid double pana (exactly two same)
                    if (/^\d{3}$/.test(digit)) {
                        const digitsArr = digit.split('');
                        const digitCount = {};
                        digitsArr.forEach(d => {
                            digitCount[d] = (digitCount[d] || 0) + 1;
                        });
                        const counts = Object.values(digitCount);
                        if (counts.includes(2) && counts.includes(1)) {
                            if (categorizedData.doublePana[digit] !== undefined) {
                                categorizedData.doublePana[digit] += points;
                            }
                        }
                    }
                    break;

                case 'Triple Pana':
                    if (categorizedData.triplePana[digit] !== undefined) {
                        categorizedData.triplePana[digit] += points;
                    }
                    break;

                case 'Half Sangam':
                    // Use combined key for display: open-close (e.g., "5-123" or "123-5")
                    const halfKey = closedigits ? `${digit}-${closedigits}` : digit;
                    if (!categorizedData.halfSangam[halfKey]) {
                        categorizedData.halfSangam[halfKey] = 0;
                    }
                    categorizedData.halfSangam[halfKey] += points;
                    break;

                case 'Full Sangam':
                    // Use combined key for display: open-close (e.g., "123-456")
                    const fullKey = closedigits ? `${digit}-${closedigits}` : digit;
                    if (!categorizedData.fullSangam[fullKey]) {
                        categorizedData.fullSangam[fullKey] = 0;
                    }
                    categorizedData.fullSangam[fullKey] += points;
                    break;
            }
        });

        // Helper function to format digits array with sorting (include all, even zeros)
        const formatDigitsArray = (digitsObj, sortByAmount = false) => {
            let entries = Object.entries(digitsObj);

            // Do NOT filter out zeros - include all
            // Sort by digit (alphabetical/numeric)
            if (sortByAmount) {
                entries.sort(([, a], [, b]) => b - a);
            } else {
                entries.sort(([a], [b]) => a.localeCompare(b, undefined, { numeric: true }));
            }

            return entries.map(([digit, amount]) => ({ digit, amount }));
        };

        // Format the response
        const responseData = {
            singleDigit: {
                title: "Single Digit",
                total: Object.values(categorizedData.singleDigit).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.singleDigit)
            },
            jodiDigit: {
                title: "Jodi Digit",
                total: Object.values(categorizedData.jodiDigit).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.jodiDigit)
            },
            singlePana: {
                title: "Single Pana",
                total: Object.values(categorizedData.singlePana).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.singlePana)
            },
            doublePana: {
                title: "Double Pana",
                total: Object.values(categorizedData.doublePana).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.doublePana)
            },
            triplePana: {
                title: "Triple Pana",
                total: Object.values(categorizedData.triplePana).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.triplePana)
            },
            halfSangam: {
                title: "Half Sangam",
                total: Object.values(categorizedData.halfSangam).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.halfSangam)
            },
            fullSangam: {
                title: "Full Sangam",
                total: Object.values(categorizedData.fullSangam).reduce((sum, val) => sum + val, 0),
                digits: formatDigitsArray(categorizedData.fullSangam)
            }
        };

        // Calculate grand total
        const grandTotal = Object.values(responseData).reduce((sum, category) => sum + category.total, 0);

        // Log some stats for debugging
        console.log("Data counts:", {
            singleDigit: responseData.singleDigit.digits.length,
            jodiDigit: responseData.jodiDigit.digits.length,
            singlePana: responseData.singlePana.digits.length,
            doublePana: responseData.doublePana.digits.length,
            triplePana: responseData.triplePana.digits.length,
            halfSangam: responseData.halfSangam.digits.length,
            fullSangam: responseData.fullSangam.digits.length
        });

        res.json({
            success: true,
            data: responseData,
            grandTotal: grandTotal,
            applied_filters: {
                date: date || '-',
                gameDB_id: gameDB_id || '-',
                session: session || '-'
            },
            recordCount: allRecords.length
        });

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



// Get content
const getContentsRules = async (req, res) => {
    try {
        const content = await content_rules_module.find();

        res.json({
            success: true,
            content
            // data: {
            //     videos: content.videos.join('\n'),
            //     gameRules: content.gameRules,
            //     withdrawRules: content.withdrawRules,
            //     depositRules: content.depositRules,
            //     homeRules: content.homeRules
            // }
        });
    } catch (error) {
        console.error('Error fetching content:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to fetch content'
        });
    }
};

// Update content
const updateContentsRules = async (req, res) => {
    try {
        const { videos, gameRules, withdrawRules, depositRules, homeRules } = req.body;
        console.log("🚀 ~ updateContentsRules ~ req.body:", req.body);

        // Find existing document or create a new one if not found
        let contentRuleData = await content_rules_module.findOne();
        if (!contentRuleData) {
            contentRuleData = new content_rules_module({});
            console.log("🆕 New contentRuleData document created");
        }

        // ✅ Update fields
        if (videos !== undefined) contentRuleData.videos = videos.trim();
        if (gameRules !== undefined) contentRuleData.gameRules = gameRules;
        if (withdrawRules !== undefined) contentRuleData.withdrawRules = withdrawRules;
        if (depositRules !== undefined) contentRuleData.depositRules = depositRules;
        if (homeRules !== undefined) contentRuleData.homeRules = homeRules;

        // Save (creates new or updates existing)
        await contentRuleData.save();

        res.json({
            success: true,
            message: contentRuleData.isNew ? 'Content created successfully' : 'Content updated successfully',
            data: {
                videos: contentRuleData.videos,
                gameRules: contentRuleData.gameRules,
                withdrawRules: contentRuleData.withdrawRules,
                depositRules: contentRuleData.depositRules,
                homeRules: contentRuleData.homeRules
            }
        });

    } catch (error) {
        console.error('Error updating content:', error);
        res.status(500).json({
            success: false,
            message: 'Failed to update content'
        });
    }
};



// const getPaymentGatewaySettings = async (req, res) => {
//     try {
//         // Get gateways from payment_gateways collection
//         const gateways = await PaymentGateway.find({}).lean();

//         // Get common settings from fix_values_module
//         const fixValues = await fix_values_module.findOne({ app_id: 1 }).lean();

//         const settings = {
//             gateways: gateways.map(gateway => ({
//                 id: gateway.gatewayId,
//                 name: gateway.name,
//                 status: gateway.status,
//                 apiKey: gateway.apiKey,
//                 clientId: gateway.clientId,
//                 secretKey: gateway.secretKey,
//                 baseUrl: gateway.baseUrl,
//                 minAmount: gateway.minAmount,
//                 maxAmount: gateway.maxAmount,
//                 processingFee: gateway.processingFee,
//                 supportedMethods: gateway.supportedMethods,
//                 testMode: gateway.testMode
//             })),
//             quickDepositAmounts: fixValues?.quickDepositAmounts || [100, 500, 1000, 2000, 5000],
//             manualPaymentEnabled: true, // Default
//             userManualPaymentMode: fixValues?.userManualPaymentMode || 0,
//             userPgPaymentMode: fixValues?.userPgPaymentMode || 0
//         };

//         return res.json({
//             success: true,
//             data: settings
//         });
//     } catch (error) {
//         console.error('Error getting payment gateway settings:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Internal server error'
//         });
//     }
// };


// const updatePaymentGatewaySettings = async (req, res) => {
//     try {
//         const {
//             gateways,
//             quickDepositAmounts,
//             manualPaymentEnabled,
//             userManualPaymentMode,
//             userPgPaymentMode
//         } = req.body;

//         // Update each gateway
//         for (const gatewayData of gateways) {
//             await PaymentGateway.findOneAndUpdate(
//                 { gatewayId: gatewayData.id },
//                 {
//                     $set: {
//                         name: gatewayData.name,
//                         status: gatewayData.status,
//                         apiKey: gatewayData.apiKey,
//                         clientId: gatewayData.clientId,
//                         secretKey: gatewayData.secretKey,
//                         baseUrl: gatewayData.baseUrl,
//                         minAmount: gatewayData.minAmount,
//                         maxAmount: gatewayData.maxAmount,
//                         processingFee: gatewayData.processingFee,
//                         supportedMethods: gatewayData.supportedMethods,
//                         testMode: gatewayData.testMode
//                     }
//                 },
//                 { upsert: true, new: true }
//             );
//         }

//         // Update common settings in fix_values
//         await fix_values_module.findOneAndUpdate(
//             { app_id: 1 },
//             {
//                 $set: {
//                     quickDepositAmounts,
//                     userManualPaymentMode: Number(userManualPaymentMode) || 0,
//                     userPgPaymentMode: Number(userPgPaymentMode) || 0
//                 }
//             },
//             { upsert: true }
//         );

//         // Log the update
//         await PaymentGatewayLog.create({
//             gatewayId: 'system',
//             type: 'settings_update',
//             request: req.body,
//             status: 'success',
//             insert_date: new Date()
//         });

//         return res.json({
//             success: true,
//             message: 'Payment gateway settings updated successfully'
//         });
//     } catch (error) {
//         console.error('Error updating payment gateway settings:', error);

//         // Log error
//         await PaymentGatewayLog.create({
//             gatewayId: 'system',
//             type: 'settings_update',
//             request: req.body,
//             status: 'failed',
//             errorMessage: error.message,
//             insert_date: new Date()
//         });

//         return res.status(500).json({
//             success: false,
//             message: 'Internal server error'
//         });
//     }
// };


const testPaymentGateway = async (req, res) => {
    try {
        const { gateway, apiKey, clientId, secretKey } = req.body;

        let testResult;
        switch (gateway) {
            case 'dollar_bazar':
                testResult = await testDollarBazarConnection(apiKey, clientId, secretKey);
                break;
            default:
                return res.status(400).json({
                    success: false,
                    message: 'Unknown gateway'
                });
        }

        // Log the test result
        await PaymentGatewayLog.create({
            gatewayId: gateway,
            type: 'connection_test',
            request: {
                apiKey: apiKey ? '***' + apiKey.slice(-4) : '',
                clientId: clientId ? '***' + clientId.slice(-4) : ''
            },
            response: testResult,
            status: testResult.success ? 'success' : 'failed',
            insert_date: new Date()
        });

        return res.json(testResult);
    } catch (error) {
        console.error('Gateway connection test error:', error);
        return res.status(500).json({
            success: false,
            message: 'Connection test failed'
        });
    }
};

const testDollarBazarConnection = async (apiKey, clientId, secretKey) => {
    try {
        // Dollar Bazar connection test - adjust endpoint as per their API
        const response = await fetch('https://collect.dollarbazar.co/api/v1/auth/verify', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}`,
                'X-Client-ID': clientId,
                'X-Secret-Key': secretKey
            },
            body: JSON.stringify({ test: true })
        });

        const data = await response.json();

        if (response.ok && data.success) {
            return {
                success: true,
                message: 'Connection successful - Credentials are valid'
            };
        } else {
            return {
                success: false,
                message: data.message || 'Invalid credentials or API endpoint'
            };
        }
    } catch (error) {
        return {
            success: false,
            message: 'Network error: ' + error.message
        };
    }
};

// Helper function to generate transaction ID
// const generateTransactionId = () => {
//     return 'TXN' + Date.now() + Math.random().toString(36).substr(2, 9).toUpperCase();
// };

// Get Payment Gateway Settings
// const getPaymentGatewaySettings = async (req, res) => {
//     try {
//         console.log("Fetching payment gateway settings...");

//         // Get gateways from payment_gateways collection
//         const gateways = await PaymentGateway_module.find({}).lean();

//         // Get common settings from fix_values_module
//         const fixValues = await fix_values_module.findOne({ app_id: 1 }).lean();

//         const settings = {
//             gateways: gateways.length > 0 ? gateways.map(gateway => ({
//                 id: gateway.gatewayId,
//                 name: gateway.name,
//                 status: gateway.status,
//                 apiKey: gateway.apiKey,
//                 clientId: gateway.clientId,
//                 secretKey: gateway.secretKey,
//                 baseUrl: gateway.baseUrl,
//                 minAmount: gateway.minAmount,
//                 maxAmount: gateway.maxAmount,
//                 processingFee: gateway.processingFee,
//                 supportedMethods: gateway.supportedMethods,
//                 testMode: gateway.testMode
//             })) : [
//                 {
//                     id: 'dollar_bazar',
//                     name: 'Dollar Bazar',
//                     status: false,
//                     apiKey: '',
//                     clientId: '',
//                     secretKey: '',
//                     baseUrl: 'https://collect.dollarbazar.co',
//                     minAmount: 100,
//                     maxAmount: 50000,
//                     processingFee: 2,
//                     supportedMethods: ['UPI', 'Net Banking', 'Card'],
//                     testMode: true
//                 }
//             ],
//             quickDepositAmounts: fixValues?.quickDepositAmounts || [100, 500, 1000, 2000, 5000],
//             manualPaymentEnabled: true,
//             userManualPaymentMode: fixValues?.userManualPaymentMode || 0,
//             userPgPaymentMode: fixValues?.userPgPaymentMode || 0
//         };

//         console.log("Settings fetched successfully");

//         return res.json({
//             success: true,
//             data: settings
//         });
//     } catch (error) {
//         console.error('Error getting payment gateway settings:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Internal server error'
//         });
//     }
// };

// // Update Payment Gateway Settings
// const updatePaymentGatewaySettings = async (req, res) => {
//     try {
//         const {
//             gateways,
//             quickDepositAmounts,
//             manualPaymentEnabled,
//             userManualPaymentMode,
//             userPgPaymentMode
//         } = req.body;

//         console.log("Updating payment gateway settings:", { gateways, quickDepositAmounts });

//         // Update each gateway
//         for (const gatewayData of gateways) {
//             await PaymentGateway_module.findOneAndUpdate(
//                 { gatewayId: gatewayData.id },
//                 {
//                     $set: {
//                         name: gatewayData.name,
//                         status: gatewayData.status,
//                         apiKey: gatewayData.apiKey,
//                         clientId: gatewayData.clientId,
//                         secretKey: gatewayData.secretKey,
//                         baseUrl: gatewayData.baseUrl,
//                         minAmount: gatewayData.minAmount,
//                         maxAmount: gatewayData.maxAmount,
//                         processingFee: gatewayData.processingFee,
//                         supportedMethods: gatewayData.supportedMethods,
//                         testMode: gatewayData.testMode
//                     }
//                 },
//                 { upsert: true, new: true }
//             );
//         }

//         // Update common settings in fix_values
//         await fix_values_module.findOneAndUpdate(
//             { app_id: 1 },
//             {
//                 $set: {
//                     quickDepositAmounts: quickDepositAmounts || [100, 500, 1000, 2000, 5000],
//                     userManualPaymentMode: Number(userManualPaymentMode) || 0,
//                     userPgPaymentMode: Number(userPgPaymentMode) || 0
//                 }
//             },
//             { upsert: true }
//         );

//         // Log the update
//         await PaymentGatewayLog_module.create({
//             // gatewayId: 'system',
//             type: 'settings_update',
//             request: {
//                 gateways: gateways.map(g => ({ id: g.id, name: g.name, status: g.status }))
//             },
//             response: { success: true },
//             status: 'success',
//             insert_date: new Date()
//         });

//         return res.json({
//             success: true,
//             message: 'Payment gateway settings updated successfully'
//         });
//     } catch (error) {
//         console.error('Error updating payment gateway settings:', error);

//         // Log error
//         await PaymentGatewayLog_module.create({
//             gatewayId: 'system',
//             type: 'settings_update',
//             request: req.body,
//             response: { error: error.message },
//             status: 'failed',
//             errorMessage: error.message,
//             insert_date: new Date()
//         });

//         return res.status(500).json({
//             success: false,
//             message: 'Internal server error: ' + error.message
//         });
//     }
// };


// Get Dollar Bazar Settings
const getDollarBazarSettings = async (req, res) => {
    try {
        const settings = await DollarBazarSettings.findOne({ gatewayId: 'dollar_bazar' });

        if (!settings) {
            // Create default if not exists
            const defaultSettings = new DollarBazarSettings({
                gatewayId: 'dollar_bazar',
                name: 'Dollar Bazar',
                status: false,
                apiKey: '',
                clientId: '',
                secretKey: '',
                salt: '',
                baseUrl: 'https://collect.dollarbazar.co',
                minAmount: 100,
                maxAmount: 50000,
                processingFee: 2,
                testMode: true
            });
            await defaultSettings.save();

            return res.json({
                success: true,
                data: defaultSettings
            });
        }

        return res.json({
            success: true,
            data: settings
        });
    } catch (error) {
        console.error('Error getting Dollar Bazar settings:', error);
        return res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
};

// Update Dollar Bazar Settings
// const updateDollarBazarSettings = async (req, res) => {
//     try {
//         const {
//             status,
//             apiKey,
//             clientId,
//             secretKey,
//             salt,
//             baseUrl,
//             minAmount,
//             maxAmount,
//             processingFee,
//             testMode
//         } = req.body;

//         const settings = await DollarBazarSettings.findOneAndUpdate(
//             { gatewayId: 'dollar_bazar' },
//             {
//                 $set: {
//                     status: status || false,
//                     apiKey: apiKey || '',
//                     clientId: clientId || '',
//                     secretKey: secretKey || '',
//                     salt: salt || '',
//                     baseUrl: baseUrl || 'https://collect.dollarbazar.co',
//                     minAmount: minAmount || 100,
//                     maxAmount: maxAmount || 50000,
//                     processingFee: processingFee || 2,
//                     testMode: testMode !== undefined ? testMode : true
//                 }
//             },
//             { upsert: true, new: true }
//         );

//         return res.json({
//             success: true,
//             message: 'Dollar Bazar settings updated successfully'
//         });
//     } catch (error) {
//         console.error('Error updating Dollar Bazar settings:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Internal server error'
//         });
//     }
// };

// Update Dollar Bazar Settings API
const updateDollarBazarSettings = async (req, res) => {
    try {
        const {
            status,
            // PayIn
            payinApiKey,
            payinSalt,
            payinClientId,
            payinBaseUrl,
            // Payout
            payoutApiKey,
            payoutSalt,
            payoutClientId,
            payoutBaseUrl,
            // Common
            minAmount,
            maxAmount,
            processingFee
        } = req.body;

        const settings = await DollarBazarSettings.findOneAndUpdate(
            { gatewayId: 'dollar_bazar' },
            {
                $set: {
                    status: status || false,

                    // PayIn
                    payinApiKey: payinApiKey || '',
                    payinSalt: payinSalt || '',
                    payinClientId: payinClientId || '',
                    payinBaseUrl: payinBaseUrl || 'https://collect.dollarbazar.co',

                    // Payout
                    payoutApiKey: payoutApiKey || '',
                    payoutSalt: payoutSalt || '',
                    payoutClientId: payoutClientId || '',
                    payoutBaseUrl: payoutBaseUrl || 'https://payout.dollarbazar.co',

                    // Common
                    minAmount: minAmount,
                    maxAmount: maxAmount,
                    processingFee: processingFee
                }
            },
            { upsert: true, new: true }
        );

        return res.json({
            success: true,
            message: 'Dollar Bazar settings updated successfully'
        });
    } catch (error) {
        console.error('Error updating Dollar Bazar settings:', error);
        return res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
};



// Test Dollar Bazar Connection
// const testDollarBazarConnection = async (req, res) => {
//     try {
//         const { apiKey, clientId, secretKey, salt } = req.body;

//         // Implement actual Dollar Bazar API test here
//         // This is a mock implementation
//         if (!apiKey || !clientId) {
//             return res.json({
//                 success: false,
//                 message: 'API Key and Client ID are required'
//             });
//         }

//         // Simulate API test
//         await new Promise(resolve => setTimeout(resolve, 1000));

//         return res.json({
//             success: true,
//             message: 'Dollar Bazar connection test successful'
//         });
//     } catch (error) {
//         console.error('Error testing Dollar Bazar connection:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Connection test failed'
//         });
//     }
// };





// Get Proton Pay Settings
const getProtonPaySettings = async (req, res) => {
    try {
        const settings = await ProtonPaySettings.findOne({ gatewayId: 'proton_pay' });

        if (!settings) {
            // Create default if not exists
            const defaultSettings = new ProtonPaySettings({
                gatewayId: 'proton_pay',
                name: 'Proton Pay',
                status: false,
                apiKey: '',
                secretKey: '',
                merchantId: '',
                baseUrl: 'https://api.protonpay.com',
                minAmount: 100,
                maxAmount: 50000,
                processingFee: 2,
                testMode: true
            });
            await defaultSettings.save();

            return res.json({
                success: true,
                data: defaultSettings
            });
        }

        return res.json({
            success: true,
            data: settings
        });
    } catch (error) {
        console.error('Error getting Proton Pay settings:', error);
        return res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
};

// Update Proton Pay Settings
const updateProtonPaySettings = async (req, res) => {
    try {
        const {
            status,
            apiKey,
            merchantCode,
            merchantKey,
            merchantId,
            baseUrl,
            // minAmount,
            // maxAmount,
            minPayin,
            maxPayin,
            processingFee,
            // secretKey,
            // testMode
        } = req.body;

        const settings = await ProtonPaySettings.findOneAndUpdate(
            { gatewayId: 'proton_pay' },
            {
                $set: {
                    status: status || false,
                    apiKey: apiKey || '',
                    // secretKey: secretKey || '',
                    merchantId: merchantId || '',
                    merchantCode: merchantCode || '',
                    merchantKey: merchantKey || '',
                    baseUrl: baseUrl || '',
                    minPayin: minPayin,
                    maxPayin: maxPayin,
                    processingFee: processingFee,
                    // testMode: testMode !== undefined ? testMode : true
                }
            },
            { upsert: true, new: true }
        );

        return res.json({
            success: true,
            message: 'Proton Pay settings updated successfully'
        });
    } catch (error) {
        console.error('Error updating Proton Pay settings:', error);
        return res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
};

// Test Proton Pay Connection
// const testProtonPayConnection = async (req, res) => {
//     try {
//         const { apiKey, merchantId, secretKey } = req.body;

//         // Implement actual Proton Pay API test here
//         // This is a mock implementation
//         if (!apiKey || !merchantId) {
//             return res.json({
//                 success: false,
//                 message: 'API Key and Merchant ID are required'
//             });
//         }

//         // Simulate API test
//         await new Promise(resolve => setTimeout(resolve, 1000));

//         return res.json({
//             success: true,
//             message: 'Proton Pay connection test successful'
//         });
//     } catch (error) {
//         console.error('Error testing Proton Pay connection:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Connection test failed'
//         });
//     }
// };













// Helper function to generate transaction ID
const generateTransactionId = () => {
    return 'TXN' + Date.now() + Math.random().toString(36).substr(2, 9).toUpperCase();
};

// Process Deposit - For Users
const processDeposit = async (req, res) => {
    try {
        const { amount, userId, payerVpa, customerEmail, customerMobile } = req.body;

        // Validate amount
        if (!amount || amount < 1) {
            return res.status(400).json({
                success: false,
                message: 'Invalid amount'
            });
        }

        // Get active payment gateways
        const suitableGateways = await payment_gateway_module.find({
            status: true,
            minAmount: { $lte: amount },
            maxAmount: { $gte: amount }
        }).sort({ processingFee: 1 });

        if (suitableGateways.length === 0) {
            return res.status(400).json({
                success: false,
                message: 'No payment gateway available for this amount range'
            });
        }

        const selectedGateway = suitableGateways[0];
        const transactionId = generateTransactionId();

        // Create deposit record with pending status
        const deposit = await add_funds_module.create({
            userDB_id: userId,
            amount: amount,
            actual_amount: amount, // Store actual amount
            tx_request_number: transactionId,
            payment_method: selectedGateway.name,
            deposit_type: 1, // Automatic PG deposit
            fund_status: 0, // Pending
            gateway_id: selectedGateway.gatewayId,
            gateway_response: {},
            insert_date: new Date()
        });

        // Initialize payment gateway service
        const gatewayService = new DollarBazarService(selectedGateway);

        // Step 1: Get authentication token
        const authResult = await gatewayService.generateAuthToken(amount, transactionId);

        if (!authResult.success) {
            // Update deposit status to failed
            await add_funds_module.findByIdAndUpdate(deposit._id, {
                fund_status: 2, // Failed
                fail_reason: authResult.message
            });

            return res.status(400).json({
                success: false,
                message: authResult.message
            });
        }

        // Step 2: Initiate UPI payment
        const paymentData = {
            amount: amount,
            orderId: transactionId,
            customerEmail: customerEmail || 'user@example.com',
            customerMobile: customerMobile || '9999999999',
            transactionRemark: `Deposit for user ${userId}`,
            payerVpa: payerVpa
        };

        const paymentResult = await gatewayService.initiateUPIPayment(authResult, paymentData);

        // Log the payment initiation
        await PaymentGatewayLog.create({
            gatewayId: selectedGateway.gatewayId,
            type: 'payment_initiate',
            request: paymentData,
            response: paymentResult,
            status: paymentResult.success ? 'success' : 'failed',
            amount: amount,
            transactionId: transactionId,
            userId: userId,
            insert_date: new Date()
        });

        if (paymentResult.success && paymentResult.data.intentUrl) {
            // Update deposit with gateway response
            await add_funds_module.findByIdAndUpdate(deposit._id, {
                gateway_response: paymentResult
            });

            return res.json({
                success: true,
                data: {
                    paymentUrl: paymentResult.data.intentUrl,
                    transactionId: transactionId,
                    gateway: selectedGateway.name,
                    status: 'pending'
                },
                message: 'Payment initiated successfully. Please complete the payment in UPI app.'
            });
        } else {
            // Update deposit status to failed
            await add_funds_module.findByIdAndUpdate(deposit._id, {
                fund_status: 2, // Failed
                fail_reason: paymentResult.message,
                gateway_response: paymentResult
            });

            return res.status(400).json({
                success: false,
                message: paymentResult.message || 'Payment initiation failed'
            });
        }

    } catch (error) {
        console.error('Deposit processing error:', error);
        return res.status(500).json({
            success: false,
            message: 'Deposit processing failed'
        });
    }
};

// Webhook Handler for Payment Callbacks
const handleWebhook = async (req, res) => {
    try {
        const {
            amount,
            transaction_status,
            transaction_datetime,
            transactionId,
            bankReference,
            orderId
        } = req.body;

        console.log('Webhook received:', req.body);

        // Find the transaction
        const deposit = await add_funds_module.findOne({
            tx_request_number: orderId
        });

        if (!deposit) {
            console.log('Transaction not found:', orderId);
            return res.status(404).send('Transaction not found');
        }

        // Log webhook received
        await PaymentGatewayLog.create({
            gatewayId: 'dollar_bazar',
            type: 'webhook_received',
            request: req.body,
            response: { status: 'processing' },
            status: 'success',
            amount: amount,
            transactionId: orderId,
            userId: deposit.userDB_id,
            insert_date: new Date()
        });

        // Update transaction based on status
        if (transaction_status === 'SUCCESS' && bankReference) {
            // Payment successful
            deposit.fund_status = 1; // Approved
            deposit.txn_ref = bankReference;
            deposit.gateway_response = {
                ...deposit.gateway_response,
                webhook: req.body,
                status: 'completed'
            };

            await deposit.save();

            // Credit user wallet
            await creditUserWallet(deposit.userDB_id, deposit.amount, deposit.tx_request_number);

            console.log(`Payment successful for order ${orderId}, UTR: ${bankReference}`);

        } else if (transaction_status === 'FAIL') {
            // Payment failed
            deposit.fund_status = 2; // Failed
            deposit.fail_reason = 'Payment failed via webhook';
            deposit.gateway_response = {
                ...deposit.gateway_response,
                webhook: req.body,
                status: 'failed'
            };

            await deposit.save();
            console.log(`Payment failed for order ${orderId}`);
        }
        // If status is INPROGRESS, we keep it as pending

        res.status(200).send('OK');
    } catch (error) {
        console.error('Webhook processing error:', error);

        await PaymentGatewayLog.create({
            gatewayId: 'dollar_bazar',
            type: 'webhook_error',
            request: req.body,
            response: { error: error.message },
            status: 'failed',
            errorMessage: error.message,
            insert_date: new Date()
        });

        res.status(500).send('Error processing webhook');
    }
};

// Check Deposit Status - For Users
const checkDepositStatus = async (req, res) => {
    try {
        const { transactionId } = req.params;
        const userId = req.body.userId; // From auth middleware

        // Find transaction
        const deposit = await add_funds_module.findOne({
            tx_request_number: transactionId,
            userDB_id: userId
        });

        if (!deposit) {
            return res.status(404).json({
                success: false,
                message: 'Transaction not found'
            });
        }

        // If already successful, return status
        if (deposit.fund_status === 1) {
            return res.json({
                success: true,
                data: {
                    status: 'success',
                    amount: deposit.amount,
                    transactionId: deposit.tx_request_number,
                    utr: deposit.txn_ref
                }
            });
        }

        // Get gateway configuration
        const gatewayConfig = await PaymentGateway_settings.findOne({
            gatewayId: deposit.gateway_id
        });

        if (!gatewayConfig) {
            return res.status(400).json({
                success: false,
                message: 'Gateway configuration not found'
            });
        }

        // Check status with payment gateway
        const gatewayService = new DollarBazarService(gatewayConfig);

        // Get auth token first
        const authResult = await gatewayService.generateAuthToken(deposit.amount, transactionId);

        if (!authResult.success) {
            return res.status(400).json({
                success: false,
                message: 'Unable to check status'
            });
        }

        const statusResult = await gatewayService.checkTransactionStatus(authResult, transactionId);

        // Log status check
        await PaymentGatewayLog.create({
            gatewayId: gatewayConfig.gatewayId,
            type: 'status_check',
            request: { transactionId },
            response: statusResult,
            status: statusResult.success ? 'success' : 'failed',
            amount: deposit.amount,
            transactionId: transactionId,
            userId: userId,
            insert_date: new Date()
        });

        if (statusResult.success && statusResult.data) {
            // Update transaction status based on gateway response
            if (statusResult.data.orderStatus === 'PAID' && statusResult.data.bankReference) {
                // Payment successful
                deposit.fund_status = 1; // Approved
                deposit.txn_ref = statusResult.data.bankReference;
                deposit.gateway_response = {
                    ...deposit.gateway_response,
                    status_check: statusResult
                };

                await deposit.save();

                // Credit user wallet
                await creditUserWallet(deposit.userDB_id, deposit.amount, deposit.tx_request_number);
            } else if (statusResult.data.status === 'FAIL') {
                // Payment failed
                deposit.fund_status = 2; // Failed
                deposit.fail_reason = statusResult.data.message || 'Payment failed';
                deposit.gateway_response = {
                    ...deposit.gateway_response,
                    status_check: statusResult
                };

                await deposit.save();
            }
        }

        return res.json({
            success: true,
            data: {
                status: deposit.fund_status === 1 ? 'success' :
                    deposit.fund_status === 2 ? 'failed' : 'pending',
                amount: deposit.amount,
                transactionId: deposit.tx_request_number,
                utr: deposit.txn_ref,
                gatewayResponse: statusResult
            }
        });

    } catch (error) {
        console.error('Status check error:', error);
        return res.status(500).json({
            success: false,
            message: 'Status check failed'
        });
    }
};

// Withdrawal Request - For Users
const requestWithdrawal = async (req, res) => {
    try {
        const { amount, userId, bankAccount, ifscCode, accountHolderName } = req.body;

        // Validate amount
        if (!amount || amount < 1) {
            return res.status(400).json({
                success: false,
                message: 'Invalid amount'
            });
        }

        // Check user balance
        const userWallet = await getUserWallet(userId);
        if (userWallet.balance < amount) {
            return res.status(400).json({
                success: false,
                message: 'Insufficient balance'
            });
        }

        const transactionId = generateTransactionId();

        // Create withdrawal request with pending status
        const withdrawal = await withdraw_fund_request_module.create({
            userDB_id: userId,
            amount: amount,
            tx_request_number: transactionId,
            bank_account: bankAccount,
            ifsc_code: ifscCode,
            account_holder_name: accountHolderName,
            withdraw_type: 1, // Automatic withdrawal
            fund_status: 0, // Pending admin approval
            insert_date: new Date()
        });

        // Deduct amount from user wallet immediately
        await deductFromWallet(userId, amount, transactionId, 'Withdrawal request');

        return res.json({
            success: true,
            data: {
                transactionId: transactionId,
                amount: amount,
                status: 'pending_approval'
            },
            message: 'Withdrawal request submitted successfully. Waiting for admin approval.'
        });

    } catch (error) {
        console.error('Withdrawal request error:', error);
        return res.status(500).json({
            success: false,
            message: 'Withdrawal request failed'
        });
    }
};

// Approve Withdrawal - For Admin
const approveWithdrawal = async (req, res) => {
    try {
        const { transactionId } = req.body;

        // Find withdrawal request
        const withdrawal = await withdraw_fund_request_module.findOne({
            tx_request_number: transactionId
        });

        if (!withdrawal) {
            return res.status(404).json({
                success: false,
                message: 'Withdrawal request not found'
            });
        }

        if (withdrawal.fund_status !== 0) {
            return res.status(400).json({
                success: false,
                message: 'Withdrawal request already processed'
            });
        }

        // Get active payment gateway for payout
        const gatewayConfig = await PaymentGateway_settings.findOne({
            status: true
        }).sort({ processingFee: 1 });

        if (!gatewayConfig) {
            return res.status(400).json({
                success: false,
                message: 'No payment gateway available'
            });
        }

        // Initialize payment gateway service
        const gatewayService = new DollarBazarService(gatewayConfig);

        // Get auth token
        const authResult = await gatewayService.generateAuthToken(withdrawal.amount, transactionId);

        if (!authResult.success) {
            // If payout fails, refund amount to user wallet
            await refundToWallet(withdrawal.userDB_id, withdrawal.amount, transactionId, 'Payout failed');

            withdrawal.fund_status = 2; // Failed
            withdrawal.fail_reason = 'Payout processing failed';
            await withdrawal.save();

            return res.status(400).json({
                success: false,
                message: 'Payout processing failed'
            });
        }

        // Process payout
        const payoutData = {
            amount: withdrawal.amount,
            orderId: transactionId,
            bankAccount: withdrawal.bank_account,
            ifscCode: withdrawal.ifsc_code,
            accountHolderName: withdrawal.account_holder_name,
            remarks: `Withdrawal for user ${withdrawal.userDB_id}`
        };

        const payoutResult = await gatewayService.processPayout(authResult, payoutData);

        // Log payout attempt
        await PaymentGatewayLog.create({
            gatewayId: gatewayConfig.gatewayId,
            type: 'payout_initiate',
            request: payoutData,
            response: payoutResult,
            status: payoutResult.success ? 'success' : 'failed',
            amount: withdrawal.amount,
            transactionId: transactionId,
            userId: withdrawal.userDB_id,
            insert_date: new Date()
        });

        if (payoutResult.success) {
            // Update withdrawal status to approved
            withdrawal.fund_status = 1; // Approved
            withdrawal.txn_ref = payoutResult.data?.transactionId;
            withdrawal.gateway_response = payoutResult;
            await withdrawal.save();

            // Create wallet transaction for completed withdrawal
            await wallet_trans_history_module.create({
                userDB_id: withdrawal.userDB_id,
                amount: withdrawal.amount,
                before_wallet: 0, // Calculate actual before balance
                transaction_type: 2, // Withdrawal
                transaction_note: `Withdrawal processed via ${gatewayConfig.name}`,
                amount_status: 20, // Withdrawal completed
                tx_request_number: transactionId,
                txn_id: payoutResult.data?.transactionId,
                payby: gatewayConfig.name
            });

            return res.json({
                success: true,
                message: 'Withdrawal approved and processed successfully'
            });
        } else {
            // If payout fails, refund amount to user wallet
            await refundToWallet(withdrawal.userDB_id, withdrawal.amount, transactionId, 'Payout failed');

            withdrawal.fund_status = 2; // Failed
            withdrawal.fail_reason = payoutResult.message || 'Payout processing failed';
            await withdrawal.save();

            return res.status(400).json({
                success: false,
                message: payoutResult.message || 'Payout processing failed'
            });
        }

    } catch (error) {
        console.error('Withdrawal approval error:', error);
        return res.status(500).json({
            success: false,
            message: 'Withdrawal approval failed'
        });
    }
};

// Reject Withdrawal - For Admin
const rejectWithdrawal = async (req, res) => {
    try {
        const { transactionId, reason } = req.body;

        // Find withdrawal request
        const withdrawal = await withdraw_fund_request_module.findOne({
            tx_request_number: transactionId
        });

        if (!withdrawal) {
            return res.status(404).json({
                success: false,
                message: 'Withdrawal request not found'
            });
        }

        if (withdrawal.fund_status !== 0) {
            return res.status(400).json({
                success: false,
                message: 'Withdrawal request already processed'
            });
        }

        // Refund amount to user wallet
        await refundToWallet(withdrawal.userDB_id, withdrawal.amount, transactionId, 'Withdrawal rejected');

        // Update withdrawal status to rejected
        withdrawal.fund_status = 2; // Rejected
        withdrawal.fail_reason = reason || 'Withdrawal rejected by admin';
        await withdrawal.save();

        return res.json({
            success: true,
            message: 'Withdrawal rejected and amount refunded to user wallet'
        });

    } catch (error) {
        console.error('Withdrawal rejection error:', error);
        return res.status(500).json({
            success: false,
            message: 'Withdrawal rejection failed'
        });
    }
};

// Wallet Helper Functions
const creditUserWallet = async (userId, amount, transactionId) => {
    try {
        // Get current wallet balance
        const latestTransaction = await wallet_trans_history_module.findOne({
            userDB_id: userId
        }).sort({ insert_date: -1 });

        const beforeWallet = latestTransaction ? latestTransaction.after_wallet : 0;
        const afterWallet = beforeWallet + amount;

        // Create wallet transaction
        await wallet_trans_history_module.create({
            userDB_id: userId,
            amount: amount,
            before_wallet: beforeWallet,
            after_wallet: afterWallet,
            transaction_type: 1, // Deposit
            transaction_note: `Deposit via Payment Gateway`,
            amount_status: 19, // User amount deposit
            tx_request_number: transactionId,
            payby: 'Payment Gateway'
        });

        console.log(`Wallet credited: User ${userId}, Amount: ${amount}`);
    } catch (error) {
        console.error('Wallet credit error:', error);
        throw error;
    }
};

const deductFromWallet = async (userId, amount, transactionId, note) => {
    try {
        // Get current wallet balance
        const latestTransaction = await wallet_trans_history_module.findOne({
            userDB_id: userId
        }).sort({ insert_date: -1 });

        const beforeWallet = latestTransaction ? latestTransaction.after_wallet : 0;

        if (beforeWallet < amount) {
            throw new Error('Insufficient balance');
        }

        const afterWallet = beforeWallet - amount;

        // Create wallet transaction
        await wallet_trans_history_module.create({
            userDB_id: userId,
            amount: amount,
            before_wallet: beforeWallet,
            after_wallet: afterWallet,
            transaction_type: 2, // Withdrawal
            transaction_note: note,
            amount_status: 21, // Withdrawal deduction
            tx_request_number: transactionId,
            payby: 'System'
        });

        console.log(`Wallet deducted: User ${userId}, Amount: ${amount}`);
    } catch (error) {
        console.error('Wallet deduction error:', error);
        throw error;
    }
};

const refundToWallet = async (userId, amount, transactionId, note) => {
    try {
        // Get current wallet balance
        const latestTransaction = await wallet_trans_history_module.findOne({
            userDB_id: userId
        }).sort({ insert_date: -1 });

        const beforeWallet = latestTransaction ? latestTransaction.after_wallet : 0;
        const afterWallet = beforeWallet + amount;

        // Create wallet transaction
        await wallet_trans_history_module.create({
            userDB_id: userId,
            amount: amount,
            before_wallet: beforeWallet,
            after_wallet: afterWallet,
            transaction_type: 1, // Credit
            transaction_note: note,
            amount_status: 22, // Refund
            tx_request_number: transactionId,
            payby: 'System'
        });

        console.log(`Wallet refunded: User ${userId}, Amount: ${amount}`);
    } catch (error) {
        console.error('Wallet refund error:', error);
        throw error;
    }
};

const getUserWallet = async (userId) => {
    try {
        const latestTransaction = await wallet_trans_history_module.findOne({
            userDB_id: userId
        }).sort({ insert_date: -1 });

        return {
            balance: latestTransaction ? latestTransaction.after_wallet : 0,
            lastTransaction: latestTransaction
        };
    } catch (error) {
        console.error('Get wallet error:', error);
        throw error;
    }
};












// const processDeposit = async (req, res) => {
//     try {
//         const { amount, userId } = req.body;

//         // Find suitable gateways based on amount
//         const suitableGateways = await PaymentGateway_module.find({
//             status: true,
//             minAmount: { $lte: amount },
//             maxAmount: { $gte: amount }
//         }).sort({ processingFee: 1 });

//         if (suitableGateways.length === 0) {
//             return res.status(400).json({
//                 success: false,
//                 message: 'No payment gateway available for this amount range'
//             });
//         }

//         const selectedGateway = suitableGateways[0];

//         // Create deposit record
//         const deposit = await add_funds_module.create({
//             userDB_id: userId,
//             amount,
//             tx_request_number: generateTransactionId(),
//             payment_method: selectedGateway.name,
//             deposit_type: 1, // Automatic
//             fund_status: 0 // Pending
//         });

//         // Process with selected gateway
//         const paymentResult = await processWithGateway(selectedGateway, deposit);

//         // Update deposit status
//         deposit.fund_status = paymentResult.success ? 1 : 2; // 1 = approved, 2 = failed
//         deposit.txn_ref = paymentResult.transactionId;
//         await deposit.save();

//         // Create wallet transaction if successful
//         if (paymentResult.success) {
//             await wallet_trans_history_module.create({
//                 userDB_id: userId,
//                 amount,
//                 before_wallet: 0, // Calculate actual before balance
//                 transaction_type: 1, // Deposit
//                 transaction_note: `Deposit via ${selectedGateway.name}`,
//                 amount_status: 19, // User amount deposit
//                 tx_request_number: deposit.tx_request_number,
//                 txn_id: paymentResult.transactionId,
//                 payby: selectedGateway.name
//             });
//         }

//         return res.json(paymentResult);
//     } catch (error) {
//         console.error('Deposit processing error:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Deposit processing failed'
//         });
//     }
// };

// const processWithGateway = async (gateway, deposit) => {
//     try {
//         // Implement specific gateway processing logic
//         switch (gateway.gatewayId) {
//             case 'dollar_bazar':
//                 return await processDollarBazarPayment(gateway, deposit);
//             // Add other gateways here
//             default:
//                 return { success: false, message: 'Unsupported gateway' };
//         }
//     } catch (error) {
//         console.error(`Error processing with ${gateway.name}:`, error);
//         return { success: false, message: error.message };
//     }
// };








// Get PG Transactions
// const getPGTransactions = async (req, res) => {
//     try {
//         const { page = 1, limit = 10, search = '', status = '', gateway = '', startDate = '', endDate = '' } = req.query;

//         // Build match query
//         let matchQuery = {
//             $or: [
//                 { payment_method: { $regex: 'dollar_bazar|payu|razorpay|cashfree|pg', $options: 'i' } },
//                 { deposit_type: 1 } // Automatic deposits (PG)
//             ]
//         };

//         // Add status filter
//         if (status && status !== 'all') {
//             if (status === 'success') {
//                 matchQuery.fund_status = 1;
//             } else if (status === 'failed') {
//                 matchQuery.fund_status = 2;
//             } else if (status === 'pending') {
//                 matchQuery.fund_status = 0;
//             }
//         }

//         // Date range filter
//         if (startDate && endDate) {
//             matchQuery.insert_date = {
//                 $gte: new Date(startDate),
//                 $lte: new Date(endDate + 'T23:59:59.999Z')
//             };
//         }

//         // Get deposit transactions
//         const deposits = await add_funds_module.aggregate([
//             { $match: matchQuery },
//             {
//                 $lookup: {
//                     from: 'users',
//                     localField: 'userDB_id',
//                     foreignField: '_id',
//                     as: 'user'
//                 }
//             },
//             { $unwind: '$user' },
//             {
//                 $lookup: {
//                     from: 'wallet_trans_histories',
//                     localField: 'tx_request_number',
//                     foreignField: 'tx_request_number',
//                     as: 'walletTx'
//                 }
//             },
//             { $unwind: { path: '$walletTx', preserveNullAndEmptyArrays: true } },
//             {
//                 $project: {
//                     id: '$_id',
//                     userDB_id: '$userDB_id',
//                     mobile: '$user.phone',
//                     username: '$user.username',
//                     amount: 1,
//                     type: 'Credit',
//                     transaction_type: 1,
//                     remark: '$payment_method',
//                     gateway: '$payment_method',
//                     status: {
//                         $switch: {
//                             branches: [
//                                 { case: { $eq: ['$fund_status', 1] }, then: 'success' },
//                                 { case: { $eq: ['$fund_status', 2] }, then: 'failed' }
//                             ],
//                             default: 'pending'
//                         }
//                     },
//                     beforeWallet: '$walletTx.before_wallet',
//                     afterWallet: { $add: ['$walletTx.before_wallet', '$amount'] },
//                     transactionId: '$tx_request_number',
//                     txn_ref: 1,
//                     payby: '$payment_method',
//                     insert_date: 1,
//                     fund_status: 1
//                 }
//             }
//         ]);

//         // Get withdrawal transactions (if PG withdrawals are supported)
//         const withdrawals = await withdraw_fund_request_module.aggregate([
//             {
//                 $match: {
//                     withdraw_type: 1, // Automatic withdrawals
//                     ...(status && status !== 'all' ? {
//                         fund_status: status === 'success' ? 1 : status === 'failed' ? 2 : 0
//                     } : {})
//                 }
//             },
//             {
//                 $lookup: {
//                     from: 'users',
//                     localField: 'userDB_id',
//                     foreignField: '_id',
//                     as: 'user'
//                 }
//             },
//             { $unwind: '$user' },
//             {
//                 $lookup: {
//                     from: 'wallet_trans_histories',
//                     localField: 'tx_request_number',
//                     foreignField: 'tx_request_number',
//                     as: 'walletTx'
//                 }
//             },
//             { $unwind: { path: '$walletTx', preserveNullAndEmptyArrays: true } },
//             {
//                 $project: {
//                     id: '$_id',
//                     userDB_id: '$userDB_id',
//                     mobile: '$user.phone',
//                     username: '$user.username',
//                     amount: 1,
//                     type: 'Debit',
//                     transaction_type: 2,
//                     remark: 'PG Withdrawal',
//                     gateway: 'Auto Withdrawal',
//                     status: {
//                         $switch: {
//                             branches: [
//                                 { case: { $eq: ['$fund_status', 1] }, then: 'success' },
//                                 { case: { $eq: ['$fund_status', 2] }, then: 'failed' }
//                             ],
//                             default: 'pending'
//                         }
//                     },
//                     beforeWallet: '$walletTx.before_wallet',
//                     afterWallet: { $subtract: ['$walletTx.before_wallet', '$amount'] },
//                     transactionId: '$tx_request_number',
//                     txn_ref: 1,
//                     payby: 'System',
//                     insert_date: 1,
//                     fund_status: 1
//                 }
//             }
//         ]);

//         // Combine and sort transactions
//         let allTransactions = [...deposits, ...withdrawals].sort((a, b) =>
//             new Date(b.insert_date) - new Date(a.insert_date)
//         );

//         // Apply search filter
//         if (search) {
//             allTransactions = allTransactions.filter(t =>
//                 t.username?.toLowerCase().includes(search.toLowerCase()) ||
//                 t.mobile?.includes(search) ||
//                 t.transactionId?.toLowerCase().includes(search.toLowerCase()) ||
//                 t.gateway?.toLowerCase().includes(search.toLowerCase())
//             );
//         }

//         // Apply gateway filter
//         if (gateway && gateway !== 'all') {
//             allTransactions = allTransactions.filter(t =>
//                 t.gateway?.toLowerCase().includes(gateway.toLowerCase())
//             );
//         }

//         // Pagination
//         const startIndex = (page - 1) * limit;
//         const endIndex = page * limit;
//         const paginatedTransactions = allTransactions.slice(startIndex, endIndex);

//         // Format dates
//         const formattedTransactions = paginatedTransactions.map(t => ({
//             ...t,
//             insert_date: new Date(t.insert_date).toLocaleString('en-IN', {
//                 year: 'numeric',
//                 month: '2-digit',
//                 day: '2-digit',
//                 hour: '2-digit',
//                 minute: '2-digit',
//                 second: '2-digit'
//             })
//         }));

//         return res.json({
//             success: true,
//             data: formattedTransactions,
//             total: allTransactions.length,
//             page: parseInt(page),
//             totalPages: Math.ceil(allTransactions.length / limit)
//         });

//     } catch (error) {
//         console.error('Error getting PG transactions:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Internal server error'
//         });
//     }
// };

// Refresh PG Transaction Status
// const refreshPGTransaction = async (req, res) => {
//     try {
//         const { transactionId } = req.body;

//         // Implementation depends on your PG's status check API
//         // This is a placeholder for actual PG status check
//         const updatedStatus = await checkPGTransactionStatus(transactionId);

//         return res.json({
//             success: true,
//             message: 'Transaction status updated',
//             data: updatedStatus
//         });

//     } catch (error) {
//         console.error('Error refreshing PG transaction:', error);
//         return res.status(500).json({
//             success: false,
//             message: 'Error refreshing transaction'
//         });
//     }
// };

const checkPGTransactionStatus = async (transactionId) => {
    // Implement actual PG status check here
    // This would call your PG's status check API
    return { status: 'success' };
};


// const sendFBNotification = async (req, res) => {
//     const { userId, title, message } = req.body;



//     const user = await user_module.findById(userId);
//     if (!user?.deviceToken) {
//         return res.status(400).json({ error: "User token not found" });
//     }

//     const result = await sendNotification(user.deviceToken, title, message);
//     return res.json({ success: true, result });
// };

// const sendFBNotification = async (req, res) => {
//     try {
//         const { target = 'all', userId, userIds, title, message } = req?.body;

//         if (!title || !message) {
//             return res.status(400).json({ error: "Title & message required" });
//         }

//         let tokens = [];

//         // ⭐ 1. Send to ALL users
//         // if (target === "all") {
//         const users = await user_module.find({ firebaseToken: { $ne: null } }).select("firebaseToken");
//         tokens = users.map(u => u.firebaseToken);
//         console.log("🚀 ~ sendFBNotification ~ tokens:", tokens)
//         // }

//         // ⭐ 2. Send to SINGLE user
//         // else if (target === "single" && userId) {
//         //     const user = await user_module.findById(userId).select("firebaseToken");
//         //     if (!user?.firebaseToken) {
//         //         return res.status(400).json({ error: "User token not found" });
//         //     }
//         //     tokens.push(user.firebaseToken);
//         // }

//         // ⭐ 3. Send to MULTIPLE users
//         // else if (target === "multiple" && Array.isArray(userIds)) {
//         //     const users = await user_module.find({ _id: { $in: userIds }, firebaseToken: { $ne: null } }).select("firebaseToken");
//         //     tokens = users.map(u => u.firebaseToken);
//         // }

//         // ⭐ 4. Send to ACTIVE users (logged within last 24 hours)
//         // else if (target === "active") {
//         //     const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
//         //     const users = await user_module.find({
//         //         lastLoginAt: { $gte: cutoff },
//         //         firebaseToken: { $ne: null }
//         //     }).select("firebaseToken");
//         //     tokens = users.map(u => u?.firebaseToken);
//         // }

//         // // ⭐ 5. Send to INACTIVE users
//         // else if (target === "inactive") {
//         //     const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000);
//         //     const users = await user_module.find({
//         //         lastLoginAt: { $lt: cutoff },
//         //         firebaseToken: { $ne: null }
//         //     }).select("firebaseToken");
//         //     tokens = users.map(u => u?.firebaseToken);
//         // }
//         // console.log("🚀 ~ sendFBNotification ~ tokens:", tokens)

//         // ⭐ Validate
//         if (!tokens.length) {
//             return res.status(400).json({ error: "No valid tokens found" });
//         }

//         // ⭐ Send notification
//         const result = await sendNotification(tokens, title, message);

//         return res.json({
//             success: true,
//             sentTo: tokens.length,
//             result
//         });

//     } catch (error) {
//         console.log("Notification error:", error);
//         return res.status(500).json({ error: "Server error" });
//     }
// };




module.exports = {
    addManualPaymentDetails,
    getManualPaymentDetails,
    deleteManualPaymentDetails,
    subAdminListGridData,
    unApprovedUserListGridData,
    getMarketBidDetails,
    getSearchMarketBidDetails,
    // autoFundRequestListGridData,
    getManualFundRequests,
    getAutoFundRequests,
    // refreshPGTransactionStatus,
    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,
    bellNotificationList,
    ideaListGridData,
    addBellNotification,
    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,
    completeStarlineBidRevert,
    decleareOpenStarlineData,
    deleteOpenStarlineResultData,
    getOpenStarlineWinnerList, // starline winner list before result
    // getOpenStarlineDeclaredWinnerList, // starline winner list after result
    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,
    fetchGalidissawarGameResultHistory,
    revertGalidissawarBids,
    getBidRevertData,
    refundAmount,
    addGamesTime,
    changeGameTime,
    tinymceUploadImage,
    addHowToPlayData,
    // sliderImagesListGridData,  // slider images
    getSliderImages,
    addSliderImage,
    deleteSliderImage,
    qrcodeImagesListGridData,
    addQrcodeImage,
    deleteQrcodeImage,
    getBidHistoryData,
    getBidArchiveHistoryData, // archive bid history
    archiveOldBids, // archive old bids
    updateBid,
    mainMarketReport,
    showDigit,
    getWinningHistoryData,
    resultHistoryListGridData,
    resultHistoryListLoadData,
    getDecleareGameData,
    saveOpenData,
    decleareOpenData_Result,
    decleareCloseData,
    saveCloseData,
    openResultNotificationContinously,


    deleteOpenCloseResultData_Result,
    deleteOpenResultData_Result,
    deleteCloseResultData_Result,
    revertBidCompletely, //bid revert


    revertOpenBids,
    revertCloseBids,



    revertMultipleBids,
    revertSingleBid,

    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,
    sendFBNotification,
    gameNameListGridDataUpdate,
    getGameRates,
    getGameList,
    getUserProfile,
    userReferralTableGridData,
    userAddFundReqTableGridData,
    userWithdrawFundReqTableGridData,
    userBitHistoryDataReqTableGridData,
    userWalletTransactionHistoryDataReqTableGridData,
    getWalletTransactionArchiveHistory,
    userWinningHistoryDataReqTableGridData,
    adminLogout,
    updateBid_with_property,
    getTransferReport,
    getWithdrawReportDetails,
    deleteStarlineGameName,
    getStarlineGameRates,
    deleteGalidisswarGameName,
    getGalidisswarGameRates,
    addGalidisswarGameRates,
    getStarlineGameList,
    getGalidisswarGameList,
    getDashboardTopData,
    getBidReportList,
    getBidWinningReportDetails,
    getWinningReportDetails,
    getStarlineBidRevertData,
    getgalidisswarBidRevertData,

    starlineDeleteBids,
    starlineDeleteSingleBid,
    starlineDeleteMultipleBids,


    galidisswarRefundAmount,
    revertGalidisswarMultipleBids,
    revertGalidisswarSingleBid,
    changeWingoResult,
    cuttingGroupData,
    getBidDetails,
    OcCuttingData,
    addManualPaymentDetails,
    createAppUpdate,
    getAppUpdates,
    toggleAppUpdateStatus,
    deleteAppUpdate,
    getLatestAppUpdate,
    moveWithdrawToProcessing,
    userTotalAddFundAndWithdrawFundAmount,
    getFixValue,
    reprocessWithdrawRequest,
    getAllUsersBankDetails,
    fetchOpenCloseGameResultHistory,
    updateMiniGamesSettings,

    getContentsRules,
    updateContentsRules,


    galiDissawarCuttingGroupData,
    getGaliDissawarBidDetails,

    starlineCuttingGroupData,
    getStarlineBidDetails,




    // getPaymentGatewaySettings,
    // updatePaymentGatewaySettings,

    getDollarBazarSettings,
    updateDollarBazarSettings,
    getProtonPaySettings,
    updateProtonPaySettings,

    // testPaymentGateway,
    // testDollarBazarConnection,

    processDeposit,
    // processWithGateway,

    // getPGTransactions,
    // refreshPGTransaction,
    checkPGTransactionStatus,
    getUserWallet,
    refundToWallet,
    deductFromWallet,
    creditUserWallet,
    rejectWithdrawal,
    approveWithdrawal,
    requestWithdrawal,
    checkDepositStatus,
    handleWebhook,
    generateTransactionId

}
