const axios = require('axios');
const crypto = require('crypto');
const moment_timeZone = require('moment-timezone');

// db models
const gali_disswar_game_result_history_module = require('../model/gali_disswar_game_result_history_module')
const gali_disswar_bid_history_module = require('../model/gali_disswar_bid_history_module');
const game_rates_module = require('../model/game_rates_module');
const user_module = require('../model/user_module');
const user_notification_module = require('../model/user_notification_module')
const game_result_history_module = require('../model/game_result_history_module');
const notice_module = require('../model/notice_module');



const SMS99_API_KEY = process.env.SMS99_API_KEY
const SMS99_ENTITY_ID = process.env.SMS99_ENTITY_ID
const SMS99_TEMPLATE_ID = process.env.SMS99_TEMPLATE_ID
const SMS99_SENDER_ID = process.env.SMS99_SENDER_ID






function toStr(v) {
    if (typeof v === 'number' && v < 0) {
        return '';
    }
    return v ? String(v).trim() : '';
}

function checkRequestAuth(app_key, env_type) {
    let db_app_key = '';

    if (env_type === 1 || env_type === '1') {
        db_app_key = process.env.APP_KEY;
    }

    if (env_type === 'Prod') {
        db_app_key = process.env.PRODUCTION_APP_KEY_APP + process.env.PRODUCTION_APP_KEY_SERVER;
        // You can also hardcode this line if needed:
        // db_app_key = 'SgRTXsywVmWteEBLlYWecwgbDiHwlh';
    }

    if (db_app_key === app_key && app_key !== '') {
        return 1;
    } else {
        return 0;
    }
}


// new 99sms service for send otp

function getOtp(mobile) {
    const mobileArray = ["9988554433", "9944332211", "9966332211", "9955332211"];

    if (mobileArray.includes(mobile)) {
        return 1234;
    } else {
        return Math.floor(Math.random() * (9999 - 1111 + 1)) + 1111;  // Random number between 1111 and 9999
    }

    // return 1234;  // Uncomment if you want to hardcode OTP
}

// async function sendMessage(mobile, message) {
//     // Full message for SMS (match your DLT template exactly; adjust if needed)
//     const smsText = message.includes(' ') ? message : `Your OTP is ${message}. Valid for 5 minutes.`;  // Handle plain OTP vs. full msg
//     console.log("🚀 ~ sendMessage ~ smsText:", smsText)

//     const url = `https://login.99smsservice.com/sms/api?` +
//         `action=send-sms&` +
//         `api_key=${SMS99_API_KEY}&` +
//         `to=${mobile}&` +
//         `from=${SMS99_SENDER_ID}&` +
//         `sms=${encodeURIComponent(smsText)}&` +
//         `p_entity_id=${SMS99_ENTITY_ID}&` +
//         `temp_id=${SMS99_TEMPLATE_ID}`;
//     console.log("🚀 ~ sendMessage ~ url:", url)

//     try {
//         const response = await axios.get(url);
//         console.log("🚀 ~ sendMessage ~ response.data:", response.data)
//         return response.data;  // Return the result from the API
//     } catch (error) {
//         console.error('Error sending message:', error);
//         return null;  // Return null if there's an error
//     }
// }





// function getOtp(mobile) {
//     const mobileArray = ["9988554433", "9944332211", "9966332211", "9955332211"];

//     if (mobileArray.includes(mobile)) {
//         return 1234;
//     } else {
//         return Math.floor(Math.random() * (9999 - 1111 + 1)) + 1111;  // Random number between 1111 and 9999
//     }

//     // return 1234;  // Uncomment if you want to hardcode OTP
// }

// async function sendMessage(mobile, message) {
//     const url = `https://api.authkey.io/request?authkey=96f965effdc558f7&mobile=${mobile}&country_code=91&sid=18990&otp=${message}`;

//     try {
//         const response = await axios.get(url);
//         return response.data;  // Return the result from the API
//     } catch (error) {
//         console.error('Error sending message:', error);
//         return null;  // Return null if there's an error
//     }
// }

async function sendMessage(mobile, message) {  // 'message' is the OTP (e.g., '2586')
    // Exact DLT-approved template (from dashboard/working URL—adjust if placeholder differs)
    const template = 'Dear User, Your OTP is {OTP} Valid for 10 minutes. Please do not share this OTP. Regards DM999 hariom';
    const smsText = template.replace('{OTP}', message);  // Or: `Dear User, Your OTP is ${message} Valid...` if no placeholder
    console.log("🚀 ~ sendMessage ~ smsText:", smsText);

    const params = new URLSearchParams({
        action: 'send-sms',
        api_key: SMS99_API_KEY,
        to: mobile,
        from: SMS99_SENDER_ID,
        sms: smsText,  // Now exact match
        p_entity_id: SMS99_ENTITY_ID,
        temp_id: SMS99_TEMPLATE_ID,
        unicode: '1'
    });

    const url = `https://login.99smsservice.com/sms/api?${params.toString()}`;
    console.log("🚀 ~ sendMessage ~ url:", url);

    try {
        const response = await axios.get(url);
        console.log("🚀 ~ sendMessage ~ response.data:", response.data);
        return response.data;
    } catch (error) {
        console.error('Error sending message:', error.response?.data || error.message);
        return null;
    }
}





function getUserRandomToken(n = Math.floor(Math.random() * 6) + 5, numberOnly = false) {
    let i = 1
    console.log("called", i);
    i++;
    const characters = numberOnly
        ? '0123456789'
        : '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

    let randomString = '';
    for (let i = 0; i < n; i++) {
        const index = Math.floor(Math.random() * characters.length);
        randomString += characters[index];
    }
    return randomString;
}

function capitalizeWords(str) {
    return str.replace(/\w\S*/g, txt => txt[0].toUpperCase() + txt.substr(1).toLowerCase());
    // return str
    //     ?.toLowerCase()
    //     .split(' ')
    //     .map(function (word) {
    //         return word.charAt(0).toUpperCase() + word.slice(1);
    //     })
    //     .join(' ');
}

/**
 * Get market status message based on open and close times (IST-based)
 * @param {Date|string} openTime - Stored open time (e.g. from MongoDB)
 * @param {Date|string} closeTime - Stored close time (e.g. from MongoDB)
 * @returns {{ msg: string, msg_status: number }}
 */
function getMsgAccordingToTime(openTime, closeTime) {
    const nowIST = moment_timeZone().tz('Asia/Kolkata');
    const todayStr = nowIST.format('YYYY-MM-DD');

    const openTimeStr = moment_timeZone(openTime).tz('Asia/Kolkata').format('HH:mm:ss');
    const closeTimeStr = moment_timeZone(closeTime).tz('Asia/Kolkata').format('HH:mm:ss');

    const todayOpenTime = moment_timeZone.tz(`${todayStr} ${openTimeStr}`, 'YYYY-MM-DD HH:mm:ss', 'Asia/Kolkata');
    let todayCloseTime = moment_timeZone.tz(`${todayStr} ${closeTimeStr}`, 'YYYY-MM-DD HH:mm:ss', 'Asia/Kolkata');

    // If close time is before open time, assume it belongs to the next day
    if (todayCloseTime.isBefore(todayOpenTime)) {
        todayCloseTime.add(1, 'day');
    }

    const data = {
        msg: '',
        msg_status: 0,
    };

    if (nowIST.isSameOrBefore(todayOpenTime)) {
        data.msg = 'Market is open';
        data.msg_status = 1;
    }
    else if (!nowIST.isSameOrBefore(todayOpenTime) && nowIST.isSameOrBefore(todayCloseTime)) {
        data.msg = 'Running for close';
        data.msg_status = 1;
    } else {
        data.msg = 'Market Closed for today';
        data.msg_status = 2;
    }

    return data;
}


// function getMsgAccordingToTime(openTime, closeTime) {
//     const nowIST = moment_timeZone().tz('Asia/Kolkata');
//     const openIST = moment_timeZone(openTime).tz('Asia/Kolkata');
//     const closeIST = moment_timeZone(closeTime).tz('Asia/Kolkata');

//     console.log('\n🕒 now:', nowIST.format());
//     console.log('🟢 open:', openIST.format());
//     console.log('🔴 close:', closeIST.format());

//     const data = { msg: '', msg_status: 0 };

//     if (nowIST.isBefore(openIST)) {
//         data.msg = 'Market Running';
//         data.msg_status = 1;
//     } else if (nowIST.isBefore(closeIST)) {
//         data.msg = 'Market Running for closed';
//         data.msg_status = 1;
//     } else {
//         data.msg = 'Market Closed';
//         data.msg_status = 2;
//     }

//     console.log('🧾 RESULT =>', data);
//     console.log('----------------------------------');
//     return data;
// }



async function declareDessawar(game) {
    const now = new Date();
    const gameId = game.game_id;
    const gameName = game.game_name;
    const resultDate = now.toISOString().split('T')[0]; // YYYY-MM-DD

    try {
        // 1. Call external API for this 'gali'
        const apiRes = await axios.post(
            'https://matkaapi.com/api/market_api.php',
            {
                domain: 'sattaloft.com',
                api_key: '64107b2d4e518',
                domain_key: 'bfc106c80740a25037049c842eec60c9',
                gali: gameName
            },
            { timeout: 1000 }
        );

        // 2. Validate and extract the 'new' number
        if (
            apiRes.data &&
            apiRes.data.status === true &&
            Array.isArray(apiRes.data.data) &&
            apiRes.data.data.length > 0
        ) {
            const apiData = apiRes.data.data[0];
            if (apiData.new) {
                const openNumber = apiData.new.toString();

                // 3. Check today's result history
                let existing = await gali_disswar_game_result_history_module.find({
                    game_id: gameId,
                    result_date: resultDate
                }).exec();
                const oldOpen = existing.length ? existing[0].open_number : null;

                // 4. If different, insert or update
                if (openNumber && openNumber !== oldOpen) {
                    if (!existing.length) {
                        const inserted = await gali_disswar_game_result_history_module.create({
                            game_id: gameId,
                            open_number: openNumber,
                            result_date: resultDate
                        });
                        existing = [inserted];
                    }

                    const record = existing[0];
                    if (record.open_decleare_status === 0) {
                        // 5. Fetch the latest rate values
                        const rates = await game_rates_module.find({}).exec();
                        const lastRate = rates[rates.length - 1] || {};
                        const {
                            single_digit_val_2,
                            single_pana_val_2,
                            double_pana_val_2
                        } = lastRate;

                        // 6. Find all open bids for this game/date
                        const bids = await gali_disswar_bid_history_module.find({
                            game_id: gameId,
                            pay_status: 0,
                            bid_date: resultDate,
                            session: 'Open'
                        }).exec();

                        // 7. Generate a unique token for this draw
                        const openResultToken = crypto.randomBytes(8).toString('hex');

                        // 8. Process each bid
                        for (const bid of bids) {
                            let winAmt = 0;
                            const digits = bid.digits.toString();

                            switch (bid.pana) {
                                case 'Left Digit':
                                    if (openNumber[0] === digits) {
                                        winAmt = (single_digit_val_2 / 10) * bid.points;
                                    }
                                    break;
                                case 'Right Digit':
                                    if (openNumber[1] === digits) {
                                        winAmt = (single_pana_val_2 / 10) * bid.points;
                                    }
                                    break;
                                case 'Jodi Digit':
                                case 'Group Jodi':
                                case 'Red Bracket':
                                    if (openNumber === digits) {
                                        winAmt = (double_pana_val_2 / 10) * bid.points;
                                    }
                                    break;
                            }

                            if (winAmt > 0) {
                                const msg = `${gameName} in ${bid.pana} for bid amount- ${bid.points} Won`;
                                // a) Update user wallet balance
                                await user_module.updateOne(
                                    { _id: bid.userDB_id },
                                    { $inc: { wallet_balance: winAmt } }
                                ).exec();
                                // b) Mark bid as paid and attach token
                                await gali_disswar_bid_history_module.updateOne(
                                    { _id: bid._id },
                                    { pay_status: 1, open_result_token: openResultToken }
                                ).exec();
                                // c) Send user notification
                                await user_notification_module.create({
                                    user_id: bid.user_id,
                                    bid_tx_id: bid.bid_tx_id,
                                    open_result_token: openResultToken,
                                    msg: `Congratulations, You Won in ${gameName} for Bid Number- ${bid.bid_tx_id}`,
                                    insert_date: now
                                });
                            }
                        }

                        // 9. Finally, mark this result as declared
                        await gali_disswar_game_result_history_module.updateOne(
                            { game_id: gameId, result_date: resultDate },
                            {
                                open_decleare_status: 1,
                                open_decleare_date: now,
                                open_result_token: openResultToken
                            }
                        ).exec();
                    }
                }
            }
        }
    } catch (error) {
        console.error('Error in declareDessawar:', error);
    }
}

/**
 * Check game status for betting based on open/close times and session.
 * @param {Date|string} open_time - ISO or Date of open time (Mongo-stored)
 * @param {Date|string} close_time - ISO or Date of close time (Mongo-stored)
 * @param {string} session - "Open" or "Close"
 * @returns {{ msg: string, game_status: number }}
 */
function checkGameStatusForBid(open_time, close_time, session) {
    const nowIST = moment_timeZone().tz('Asia/Kolkata');

    // Parse open and close times and set them to today's date in IST
    const todayDateStr = nowIST.format('YYYY-MM-DD');

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

    let data = {};

    if (session === 'Open' && nowIST.isAfter(openTimeIST)) {
        data.msg = 'Sorry Open session for this Betting Is Closed';
        data.game_status = 2;
    } else if (nowIST.isSameOrBefore(closeTimeIST)) {
        data.msg = 'Betting Is Running.';
        data.game_status = 1;
    } else {
        data.msg = 'Betting Closed';
        data.game_status = 2;
    }

    // Override: If close time is between midnight and 5 AM IST → force open
    const closeHour = closeTimeIST.hour();
    if (closeHour >= 0 && closeHour < 5) {
        data.msg = 'Betting Is Running.';
        data.game_status = 1;
    }

    return data;
}

function checkGameStatus(open_time, close_time) {
    const now = new Date();
    const today = now.toISOString().slice(0, 10); // "YYYY-MM-DD"

    const openDt = parse12h(open_time);
    const closeDt = parse12h(close_time);

    if (now < openDt) {
        return {
            msg: 'Betting has not opened yet.',
            msg_hindi: 'बेटिंग अभी शुरू नहीं हुई है',
            game_status: 0,
            status: false
        };
    }
    else if (now <= closeDt) {
        return {
            msg: 'Betting is running.',
            msg_hindi: 'बेटिंग चालू है',
            game_status: 1,
            status: true
        };
    }
    else {
        return {
            msg: 'Sorry, betting is closed.',
            msg_hindi: 'क्षमा करें, बेटिंग बंद है',
            game_status: 2,
            status: false
        };
    }
}

async function resultDeclare(openTime, closeTime, gameId, gameName) {
    function parseTimeToToday(timeStr) {
        // timeStr like "10:10 AM"
        const [timePart, modifier] = timeStr.split(' ');
        let [hours, minutes] = timePart.split(':').map(Number);
        if (modifier === 'PM' && hours !== 12) hours += 12;
        if (modifier === 'AM' && hours === 12) hours = 0;
        const d = new Date();
        d.setHours(hours, minutes, 0, 0);
        return d;
    }
    const now = new Date();
    const todayStr = now.toISOString().slice(0, 10);
    const yesterday = new Date(now);
    yesterday.setDate(yesterday.getDate() - 1);
    const yesterdayStr = yesterday.toISOString().slice(0, 10);

    const openDt = parseTimeToToday(openTime);
    const closeDt = parseTimeToToday(closeTime);

    // only proceed 15 minutes after open:
    if (now < new Date(openDt.getTime() + 15 * 60_000)) {
        return;
    }

    // fetch today’s and yesterday’s declared results
    const [todayResults, yesterdayResults] = await Promise.all([
        game_result_history_module.findOne({ gameDB_id: gameId, resultDate: todayStr }),
        game_result_history_module.findOne({ gameDB_id: gameId, resultDate: yesterdayStr }),
    ]);

    // check if we still need to declare
    const todayEntry = todayResults || {};
    if (todayEntry.open_decleare_status && todayEntry.close_decleare_status) {
        return;
    }

    // call the external API
    let api;
    try {
        const resp = await axios.post('https://matkaapi.com/api/market_api.php', {
            domain: 'sattaloft.com',
            api_key: '64107b2d4e518',
            domain_key: 'bfc106c80740a25037049c842eec60c9',
            market: gameName
        }, {
            timeout: 1_000,
            headers: { 'User-Agent': 'api' }
        });
        api = resp.data;
    } catch (err) {
        console.error('API error', err);
        return;
    }

    if (!api.status || !api.data?.length) {
        return;
    }

    const [raw] = api.data;
    if (!raw.result) {
        return;
    }

    const parts = raw.result.split('-');
    const [openNum, , closeNum] = parts.map(p => p.trim());

    // declare open if needed
    if (!todayEntry.openDeclared && parseInt(openNum) !== yesterdayResults?.open_number) {
        await declareOpenResult(gameId, parseInt(openNum));
    }

    // declare close if it’s a three‑part result and time’s up
    if (
        parts.length === 3 &&
        now >= new Date(closeDt.getTime() + 15 * 60_000) &&
        (!todayEntry.closeDeclared && parseInt(closeNum) !== yesterdayResults?.close_number)
    ) {
        // note: pass closeDt minus 15 minutes if you need that original timestamp
        await declareCloseResult(gameId, closeNum, new Date(closeDt.getTime() - 15 * 60_000));
    }
}

async function declareOpenResult(gameId, openNumber) {
    const now = new Date();
    const dateStr = now.toISOString().slice(0, 10);

    // upsert today’s open number
    await game_result_history_module.updateOne(
        { gameDB_id: gameId, resultDate: dateStr },
        {
            $set: {
                open_number: openNumber,
                open_decleare_status: 1,
                open_decleare_date: now,
                open_result_token: getUserRandomToken(15),   // e.g. your uniqRandom
            }
        },
        { upsert: true }
    );

    // …then pull in bets for the “Open” session, compute winners, update wallets,
    // send notifications, etc., exactly as in your PHP but using async/await and Mongoose.
}

async function declareCloseResult(gameId, closeNumber, closeTime) {
    let declDate = new Date();
    // if closeTime is between 00:00 and 05:00, roll declaration date back one day
    const hhmm = closeTime.toTimeString().slice(0, 5);  // "HH:MM"
    if (hhmm >= '00:00' && hhmm <= '05:00') {
        declDate.setDate(declDate.getDate() - 1);
    }
    const dateStr = declDate.toISOString().slice(0, 10);

    // only update if openDeclared was already true and closeDeclared still false
    const todayEntry = await Result.findOne({ gameId, resultDate: dateStr });
    if (!todayEntry?.openDeclared || todayEntry.closeDeclared) {
        return;
    }

    await Result.updateOne(
        { gameId, resultDate: dateStr },
        {
            $set: {
                closeNumber,
                closeDeclared: true,
                closeDeclaredAt: new Date(),
                closeResultToken: getUserRandomToken(15),
            }
        }
    );

    // …then process all pending “Open” bets, compute close‑session winners,
    // update wallets, send notifications, etc.
}

// helper: turn "08:30 PM" → Date("YYYY-MM-DDT20:30:00")
function parse12h(time12) {
    let [time, meridiem] = time12.split(' ');
    let [h, m] = time.split(':').map(Number);

    if (meridiem === 'PM' && h !== 12) h += 12;
    if (meridiem === 'AM' && h === 12) h = 0;

    // pad back to "HH:MM:SS"
    const hh = h.toString().padStart(2, '0');
    const mm = m.toString().padStart(2, '0');
    return new Date(`${today}T${hh}:${mm}:00`);
}

// helper: turn Date("YYYY-MM-DDT20:30:00") → "08:30 PM"
function formatTime12Hour(date) {
    return date.toLocaleTimeString('en-US', {
        hour: '2-digit',
        minute: '2-digit',
        hour12: true
    });
}

// helper: turn "08:30 PM" → "20:30:00"
function convert12To24(time12h) {
    const [time, modifier] = time12h.split(' ');
    let [hours, minutes] = time.split(':');

    if (hours === '12') {
        hours = '00';
    }
    if (modifier.toUpperCase() === 'PM') {
        hours = String(parseInt(hours, 10) + 12);
    }

    hours = hours.padStart(2, '0');
    minutes = minutes.padStart(2, '0');

    return `${hours}:${minutes}:00`;
}

// helper: turn "20:30:00" or "20:30" → "08:30:00 PM" or "08:30 PM"
function convert24To12(time24h) {
    const parts = time24h.split(':');
    let [hours, minutes, seconds] = [parts[0], parts[1], parts[2]];

    hours = parseInt(hours, 10);
    const ampm = hours >= 12 ? 'PM' : 'AM';
    hours = hours % 12;
    if (hours === 0) hours = 12;

    const strHours = String(hours).padStart(2, '0');
    const strMinutes = String(minutes).padStart(2, '0');

    if (seconds !== undefined) {
        const strSeconds = String(seconds).padStart(2, '0');
        return `${strHours}:${strMinutes}:${strSeconds} ${ampm}`;
    } else {
        return `${strHours}:${strMinutes} ${ampm}`;
    }
}

function checkGameOpenStatus(openTime) {
    const istNow = moment_timeZone().tz('Asia/Kolkata'); // current time in IST

    console.log(`(((((((()))))) ~ helper_functions.js:535 ~ checkGameOpenStatus ~ istNow:`, istNow);

    // Parse openTime (format: "hh:mm AM/PM")
    const openMoment = moment_timeZone.tz(openTime, 'hh:mm A', 'Asia/Kolkata');

    console.log(`(((((((()))))) ~ helper_functions.js:538 ~ checkGameOpenStatus ~ openMoment:`, openMoment);

    // Set today's date for openMoment
    openMoment.set({
        year: istNow.year(),
        month: istNow.month(),
        date: istNow.date()
    });

    // If current time is before the open time
    if (istNow.isBefore(openMoment)) {
        return {
            msg: 'Betting is Running.',
            game_status: 1,
            success: true
        };
    } else {
        return {
            msg: 'Sorry, Betting is Closed.',
            game_status: 2,
            success: false
        };
    }
}


function getMsgAccordingToOpenTime(openTime) {
    const now = new Date();

    // Parse "hh:mm AM/PM" into a Date for today
    const [time, meridiem] = openTime.split(' ');
    let [hours, minutes] = time.split(':').map(Number);

    if (meridiem === 'PM' && hours !== 12) hours += 12;
    if (meridiem === 'AM' && hours === 12) hours = 0;

    const today = now.toISOString().slice(0, 10);  // "YYYY-MM-DD"
    const hh = String(hours).padStart(2, '0');
    const mm = String(minutes).padStart(2, '0');
    const openDt = new Date(`${today}T${hh}:${mm}:00`);

    if (now < openDt) {
        return {
            msg: 'Market Running',
            msg_hindi: 'बाजार खुला',
            msg_status: 1
        };
    } else {
        return {
            msg: 'Market Closed',
            msg_hindi: 'बाजार बंद',
            msg_status: 2
        };
    }
}

function getMsgAccordingToTimeRouletteActive(open_time, close_time) {
    const now = new Date();

    // Convert '05:15 PM' to 24-hour format and build Date objects
    const todayStr = now.toISOString().split('T')[0]; // "YYYY-MM-DD"

    function parseTime(timeStr) {
        const [time, meridian] = timeStr.split(' ');
        let [hours, minutes] = time.split(':').map(Number);

        if (meridian === 'PM' && hours < 12) hours += 12;
        if (meridian === 'AM' && hours === 12) hours = 0;

        return new Date(`${todayStr}T${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00`);
    }

    const openDate = parseTime(open_time);
    const closeDate = parseTime(close_time);

    let data = {};
    if (now >= openDate && now <= closeDate) {
        data.msg = 'Betting is running for today';
        data.msg_hindi = 'बेटीन्ग आज के लिए बंद है';
        data.msg_status = 1;
    } else {
        data.msg = 'Betting will open soon';
        data.msg_hindi = 'बेटीन्ग जल्द खुलेगा';
        data.msg_status = 2;
    }

    return data;
}

function getPossibleCombination(chars, size, combinations = []) {
    if (combinations.length === 0) {
        combinations = [...chars];
    }

    if (size === 1) {
        return combinations;
    }

    const newCombinations = [];
    for (const combination of combinations) {
        for (const char of chars) {
            newCombinations.push(combination + char);
        }
    }

    return getPossibleCombination(chars, size - 1, newCombinations);
}

const noticeSender = async (to, title, message) => {
    try {
        if (to === 'all') {
            await notice_module.create({ notice_title: title, notice_msg: message })
        } else {
            notice_module.create({ phone: to, notice_title: title, notice_msg: message })
        }
        return true;
    } catch (error) {
        console.error('Error sending Notice:', error);
        throw error;
    }
};

module.exports = {
    toStr,
    checkRequestAuth,
    getOtp,
    sendMessage,
    getUserRandomToken,
    capitalizeWords,
    getMsgAccordingToTime,
    declareDessawar,
    checkGameStatus,
    resultDeclare,
    checkGameStatusForBid,
    checkGameOpenStatus,
    getMsgAccordingToOpenTime,
    getMsgAccordingToTimeRouletteActive,
    getPossibleCombination,
    noticeSender,
    formatTime12Hour,
    parse12h,
    convert12To24,
    convert24To12,
}